踩坑实录:在 VMware Ubuntu 22.04 Server 上部署 Minikube 的血泪史

背景与环境

最近想重新学习一下 Kubernetes,为了图方便,决定在本地 VMware 虚拟机里装一个 Minikube。原本以为是一路回车的事,没想到硬是折腾了一下午,经历了各种网络、内存、镜像和 CNI 的折磨。

环境信息:

  • 虚拟机:VMware Workstation,Ubuntu 22.04 Server(无图形界面)
  • 虚拟机 IP:192.168.65.194(NAT 模式)
  • 宿主机代理:192.168.65.1:7890(HTTP/HTTPS 代理)
  • 虚拟机配置:中途扩容至 4 核 8G,60G 硬盘
  • 目标:使用 Docker 驱动启动 Minikube,并运行 Dashboard 及测试应用

本文记录了我这一路遇到的各种报错和最终的成功配置,希望能帮到遇到类似问题的朋友。


第一坑:宿主机代理与 GitHub 连接被拒

一开始按照官方文档下载 Minikube 二进制文件:

x12@chenjx12:~$ curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:00:21 --:--:--     0
curl: (7) Failed to connect to github.com port 443 after 21059 ms: Connection refused
[sudo] password for x12:                                            
install: cannot stat 'minikube-linux-amd64': No such file or directory

原因:虚拟机是 NAT 网络,无法直接访问外网,需要走宿主机的代理。但宿主机默认只监听 127.0.0.1。

解决:

  1. 在宿主机代理软件中开启 “允许局域网连接”(Allow LAN)。
  2. 在虚拟机终端中手动配置代理:
export http_proxy="http://192.168.65.1:7890"
export https_proxy="http://192.168.65.1:7890"
export all_proxy="socks5://192.168.65.1:7890"

(如需永久生效,可写入 ~/.bashrc;如需让 apt 走代理,需配置 /etc/apt/apt.conf.d/proxy.conf)


第二坑:内存不足导致集群 OOM 崩溃

在一开始的虚拟机配置(4G内存)下,执行 minikube start 时提示:

🧯 The requested memory allocation of 3072MiB does not leave room for system overhead (total system memory: 3875MiB). You may face stability issues.

紧接着,集群刚启动没多久,Docker 容器直接死掉,kubectl 报错:

x12@chenjx12:~$ minikube kubectl -- get po -A
E0928 07:26:45.799491   27227 memcache.go:381] "Couldn't get current server API group list" err="Get \"https://192.168.49.2:8443/api?timeout=32s\": context deadline exceeded - error from a previous attempt: read tcp 192.168.65.194:57730->192.168.65.1:7890: read: connection reset by peer"

查看 Docker 容器状态发现 Minikube 容器 Exited (255):

x12@chenjx12:~$ docker ps -a | grep minikube
6cda0179e356   gcr.io/k8s-minikube/kicbase:v0.0.51   "/usr/local/bin/entr…"   12 minutes ago   Exited (255) About a minute ago   127.0.0.1:32783->22/tcp, ...   minikube

原因:Minikube 默认申请 3G 内存,宿主机系统本身还要占用 1G 多,导致触发 Linux OOM Killer,Minikube 容器被系统强行杀死。

解决: 将 VMware 虚拟机内存扩容到 8GB,后续启动时限制 Minikube 使用 --memory=4096,给系统留足空间。


第三坑:国内镜像源与二进制文件 404 陷阱

为了提高速度,我一开始使用了国内镜像仓库参数:

bash

minikube start --driver=docker \
  --image-mirror-country='cn' \
  --docker-env=HTTP_PROXY=http://192.168.65.1:7890 \
  --docker-env=HTTPS_PROXY=http://192.168.65.1:7890 \
  --docker-env=NO_PROXY=localhost,127.0.0.1,192.168.49.0/24

结果不断报错:

❌ Exiting due to K8S_INSTALL_FAILED: Failed to update cluster: update primary control-plane node: downloading binaries: downloading kubelet: download failed: https://kubernetes.oss-cn-hangzhou.aliyuncs.com/kubernetes-release/release/v1.37.0/bin/linux/amd64/kubelet?checksum=file:https://kubernetes.oss-cn-hangzhou.aliyuncs.com/kubernetes-release/release/v1.37.0/bin/linux/amd64/kubelet.sha256: getter: &{...}: invalid checksum: Error downloading checksum file: bad response code: 404

尝试指定版本 v1.32.0 并更换二进制镜像源,依然 404:

❌ Exiting due to K8S_INSTALL_FAILED: Failed to update cluster: update primary control-plane node: downloading binaries: downloading kubectl: download failed: https://kubernetes-release.pek3b.qingstor.com/v1.32.0/bin/linux/amd64/kubectl?checksum=file:https://kubernetes-release.pek3b.qingstor.com/v1.32.0/bin/linux/amd64/kubectl.sha256: getter: &{...}: invalid checksum: Error downloading checksum file: bad response code: 404

原因:

  1. --image-mirror-country='cn' 会强行把 Minikube 的二进制文件下载源也切到阿里云 OSS。
  2. 阿里云 OSS 等国内源严重滞后,根本没同步 v1.30.0 或更高版本的 kubelet、kubectl、kubeadm 的校验文件,所以直接 404。
  3. 更坑的是,只要用了 --image-repository,Minikube 就会自动触发这个行为。

解决: 彻底放弃国内镜像源参数,只要宿主机代理稳定,直接让它走官方源即可。


第四坑:权限残留导致删除失败

在反复重试的过程中,minikube delete --all --purge 经常报错:

❌  Exiting due to HOST_HOME_PERMISSION: unlinkat /home/x12/.minikube/cache/preloaded-tarball/preloaded-images-k8s-v18-v1.32.0-containerd-overlay2-amd64.tar.lz4: permission denied
💡  Suggestion: Your user lacks permissions to the minikube profile directory. Run: 'sudo chown -R $USER $HOME/.minikube; chmod -R u+wrx $HOME/.minikube' to fix

解决:千万不要去改 ownership 权限,直接暴力清除即可:

sudo rm -rf ~/.minikube

第五坑:kindnet CNI 插件无休止崩溃

即使解决了下载问题,默认的 CNI 网络插件 kindnet 却一直在 Pending、ErrImagePull、CrashLoopBackOff 和 Error 之间反复横跳:

x12@chenjx12:~$ kubectl get po -A
NAMESPACE     NAME                               READY   STATUS             RESTARTS      AGE
kube-system   coredns-6cf5fbd489-pcqn2           0/1     Pending            0             13s
kube-system   kindnet-8z5rk                      0/1     CrashLoopBackOff   1 (6s ago)    13s
kube-system   kube-scheduler-minikube            1/1     Running            0             21s
...

kubectl describe 查看详情,发现 kindnet 容器退出码 255,且无日志:

x12@chenjx12:~$ kubectl describe pod kindnet-8z5rk -n kube-system
...
    State:          Terminated
      Reason:       Error
      Exit Code:    255
...
Events:
  Warning  BackOff    33s (x4 over 68s)  kubelet            spec.containers{kindnet-cni}: Back-off restarting failed container kindnet-cni in pod kindnet-8z5rk_kube-system(...)

进入 Minikube 节点排查:

x12@chenjx12:~$ minikube ssh
docker@minikube:~$ cd /etc/cni/net.d/
docker@minikube:/etc/cni/net.d$ ls -la
total 24
drwxr-xr-x 1 root root 4096 Sep 28 07:53 .
drwxr-xr-x 1 root root 4096 Sep  1 18:13 ..
-rw-r--r-- 1 root root  469 Aug 25 02:16 10-crio-bridge.conflist.disabled.mk_disabled
-rw-r--r-- 1 root root  639 Nov 13  2022 87-podman-bridge.conflist.mk_disabled
-rw-r--r-- 1 root root    0 Sep 28 07:52 cni.lock

发现没有任何有效的 CNI 配置文件,只有被禁用的旧文件和一个空的锁文件。

最终定位原因有两个:

  1. Ubuntu 22.04 宿主机默认没有加载 br_netfilter 和 overlay 内核模块,导致网络插件无法配置网桥。
  2. kindnet 在 Docker 驱动下的兼容性极差,极易崩溃。

解决:

  1. 提前加载内核模块:
sudo modprobe br_netfilter
sudo modprobe overlay
lsmod | grep -E 'br_netfilter|overlay'
# 输出:
br_netfilter           32768  0
bridge                311296  1 br_netfilter
overlay               151552  0
  1. 更换稳定成熟的 CNI 插件为 Flannel,添加参数 --cni=flannel。

第六坑:Dashboard 部署与镜像拉取的无底洞

集群终于跑起来了,但真正的噩梦才刚刚开始——为了看到那个图形化界面(Dashboard),我又陷入了无尽的镜像拉取与端口转发的折磨。

6.1 minikube dashboard --url 无限卡死

执行官方提供的命令:

x12@chenjx12:~$ minikube dashboard --url
🔌  Enabling dashboard ...
    ▪ Using image docker.io/kubernetesui/dashboard:v2.7.0
    ▪ Using image docker.io/kubernetesui/metrics-scraper:v1.0.8
🤔  Verifying dashboard health ...
🚀  Launching proxy ...
🤔  Verifying proxy health ...
❌  Exiting due to SVC_URL_TIMEOUT: http://127.0.0.1:44439/... is not accessible: Temporary Error: unexpected response code: 503

原因:503 说明代理通了,但后端 Dashboard 的 Pod 没就绪(处于 Pending 或 ImagePullBackOff)。

6.2 端口转发报错找不到端口

尝试用 kubectl port-forward 绕过 minikube dashboard:

x12@chenjx12:~$ kubectl port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8443:443 --address 0.0.0.0
error: Service kubernetes-dashboard does not have a service port 443

原因:新版 Dashboard 服务名和端口变了,查一下实际的 Service:

x12@chenjx12:~$ kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
dashboard-metrics-scraper   ClusterIP   10.98.45.31      <none>        8000/TCP   8m16s
kubernetes-dashboard        ClusterIP   10.109.123.237   <none>        80/TCP     8m16s

服务名是 kubernetes-dashboard,端口是 80,不是 443。

6.3 镜像拉取失败(ImagePullBackOff)

查看 Pod 状态,发现两个 Pod 都拉不到镜像:

x12@chenjx12:~$ kubectl get pods -n kubernetes-dashboard
NAME                                        READY   STATUS             RESTARTS   AGE
dashboard-metrics-scraper-b5fc48f67-v677v   0/1     ErrImagePull       0          12m
kubernetes-dashboard-779776cb65-ssb5k       0/1     ImagePullBackOff   0          12m

原因:Minikube 内部的 containerd 没有走宿主机的代理,无法从 Docker Hub 拉取镜像。 解决:在宿主机 Docker 拉取镜像,再导入 Minikube。

# 1. 用 Docker 拉取镜像(Docker 已配代理)
docker pull docker.io/kubernetesui/dashboard:v2.7.0
docker pull docker.io/kubernetesui/metrics-scraper:v1.0.8

# 2. 导出为 tar 包
docker save docker.io/kubernetesui/dashboard:v2.7.0 -o dashboard.tar
docker save docker.io/kubernetesui/metrics-scraper:v1.0.8 -o metrics-scraper.tar

# 3. 复制进 Minikube 节点,直接用 ctr 导入 containerd
minikube cp dashboard.tar /tmp/dashboard.tar
minikube cp metrics-scraper.tar /tmp/metrics-scraper.tar
minikube ssh
sudo ctr -n k8s.io images import /tmp/dashboard.tar
sudo ctr -n k8s.io images import /tmp/metrics-scraper.tar
sudo crictl images | grep -E "dashboard|metrics"
# 输出成功:
# docker.io/kubernetesui/dashboard          v2.7.0               07655ddf2eebe       75.8MB
# docker.io/kubernetesui/metrics-scraper    v1.0.8               115053965e86b       19.7MB
exit

6.4 终极顽固错误:ErrImageNeverPull

镜像明明导入成功了,但 Pod 仍然报错:

x12@chenjx12:~$ kubectl get pods -n kubernetes-dashboard
NAME                                         READY   STATUS              RESTARTS   AGE
dashboard-metrics-scraper-6979486cbb-qpwbm   0/1     ErrImageNeverPull   0          74s
kubernetes-dashboard-74f48949b4-rgjnr        0/1     ErrImageNeverPull   0          74s

检查 Deployment 配置发现端倪:

x12@chenjx12:~$ kubectl get deployment kubernetes-dashboard -n kubernetes-dashboard -o yaml | grep -A 2 "image:"
        image: docker.io/kubernetesui/dashboard:v2.7.0@sha256:2e500d29e9d5f4a086b908eb8dfe7ecac57d2ab09d65b24f588b1d449841ef93
        imagePullPolicy: Never

原因:

  1. 镜像名称带了 @sha256:... 摘要,与 containerd 里的 v2.7.0 标签不匹配。
  2. imagePullPolicy: Never 强制只使用本地镜像,找不到就直接报 ErrImageNeverPull。

解决:手动编辑 Deployment,删掉 @sha256:...,并把 imagePullPolicy 改为 IfNotPresent。

kubectl edit deployment kubernetes-dashboard -n kubernetes-dashboard
# 修改 image 为 docker.io/kubernetesui/dashboard:v2.7.0
# 修改 imagePullPolicy 为 IfNotPresent
kubectl edit deployment dashboard-metrics-scraper -n kubernetes-dashboard
# 同理修改 metrics-scraper

# 删除旧 Pod 重建
kubectl delete pod -n kubernetes-dashboard --all

6.5 最终成功:端口转发 + SSH 隧道

Pod 终于 Running 了:

x12@chenjx12:~$ kubectl get pods -n kubernetes-dashboard
NAME                                         READY   STATUS    RESTARTS   AGE
dashboard-metrics-scraper-6bcb468bfc-x7c62   1/1     Running   0          8s
kubernetes-dashboard-7bbdfddc7c-cfj89        1/1     Running   0          8s

虚拟机终端里(保持运行):

kubectl port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8443:80 --address 0.0.0.0
# 输出:Forwarding from 0.0.0.0:8443 -> 80

宿主机终端里(PowerShell/CMD,保持运行):

ssh -L 8443:127.0.0.1:8443 x12@192.168.65.194

宿主机浏览器访问 http://127.0.0.1:8443,如果有 Token 验证,在虚拟机里执行:

kubectl -n kubernetes-dashboard create token kubernetes-dashboard

复制长字符串粘贴到浏览器登录框。至此,Dashboard 终于完美展现!


第七坑:Pod 无法拉取应用镜像 —— containerd 代理缺失

当我在 Dashboard 里尝试部署一个测试应用 hello-minikube 时,又遇到了熟悉的拉取失败:

kubectl create deployment hello-minikube --image=kicbase/echo-server:1.0

Dashboard 和命令行都报错:

Failed to pull image "kicbase/echo-server:1.0": failed to pull and unpack image "docker.io/kicbase/echo-server:1.0": failed to resolve reference "docker.io/kicbase/echo-server:1.0": failed to do request: Head "https://registry-1.docker.io/v2/kicbase/echo-server/manifests/1.0": dial tcp 31.13.87.34:443: connect: connection refused

原因:--docker-env 注入的代理变量只对 Docker 容器生效,而 Pod 运行时使用的是 containerd,两者环境隔离。containerd 没有走代理,无法访问 Docker Hub。

解决:

  1. 快速方案:手动导入镜像(同 6.3,将 dashboard 换成 kicbase/echo-server:1.0)。
docker pull kicbase/echo-server:1.0
docker save kicbase/echo-server:1.0 -o echo-server.tar
minikube cp echo-server.tar /tmp/echo-server.tar
minikube ssh
sudo ctr -n k8s.io images import /tmp/echo-server.tar
exit
kubectl delete pod -n default -l app=hello-minikube
  1. 根治方案:给 Minikube 内部的 containerd 配置代理。
minikube ssh
sudo mkdir -p /etc/systemd/system/containerd.service.d/
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://192.168.65.1:7890"
Environment="HTTPS_PROXY=http://192.168.65.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.49.0/24,10.96.0.0/12,10.244.0.0/16"
EOF
sudo systemctl daemon-reload
sudo systemctl restart containerd
exit

(注意:此配置在 Minikube 重启后可能会丢失,建议每次重启后重新执行,或写进启动脚本)。

image-20260928170246008

启动脚本(附赠)

为了避免每次重启虚拟机后手动配置 containerd 代理,我写了一个一键启动脚本。它自动完成内核模块加载、Minikube 启动、containerd 代理注入、等待就绪等步骤。

完整脚本见上文,保存为 ~/start-minikube.sh 并 chmod +x 后即可使用。如果想开机自启,配合 crontab -e 添加 @reboot 任务即可。

这样以后每次打开虚拟机,只需要跑一次脚本,就能直接进入一个完全就绪的 Kubernetes 环境。

start-minikube.sh

#!/bin/bash
# ============================================================
# Minikube 一键启动脚本
# 适用环境:VMware Ubuntu 22.04 Server + Docker 驱动 + 宿主机代理
# ============================================================

# ---------------- 可配置变量 ----------------
PROXY_HOST="192.168.65.1"        # 宿主机代理 IP
PROXY_PORT="7890"                # 宿主机代理端口
MINIKUBE_MEMORY="4096"           # Minikube 分配内存(MB)
MINIKUBE_CPUS="2"                # Minikube 分配 CPU 核数
K8S_VERSION="v1.30.0"            # Kubernetes 版本
CNI_PLUGIN="flannel"             # CNI 插件
VM_USER="x12"                    # 虚拟机用户名
VM_IP="192.168.65.194"           # 虚拟机 IP
# -------------------------------------------

PROXY_URL="http://${PROXY_HOST}:${PROXY_PORT}"
NO_PROXY_LIST="localhost,127.0.0.1,192.168.49.0/24,10.96.0.0/12,10.244.0.0/16"

echo "=========================================="
echo " 1. 检查 Docker 代理配置"
echo "=========================================="
if ! docker info 2>/dev/null | grep -q "HTTP Proxy"; then
    echo "⚠️  Docker 未配置代理,正在配置..."
    sudo mkdir -p /etc/systemd/system/docker.service.d
    sudo tee /etc/systemd/system/docker.service.d/proxy.conf > /dev/null <<EOF
[Service]
Environment="HTTP_PROXY=${PROXY_URL}"
Environment="HTTPS_PROXY=${PROXY_URL}"
Environment="NO_PROXY=localhost,127.0.0.1,192.168.65.0/24"
EOF
    sudo systemctl daemon-reload
    sudo systemctl restart docker
    echo "✅ Docker 代理已配置"
else
    echo "✅ Docker 代理已就绪"
fi

echo ""
echo "=========================================="
echo " 2. 加载内核模块"
echo "=========================================="
sudo modprobe br_netfilter
sudo modprobe overlay
lsmod | grep -E 'br_netfilter|overlay' > /dev/null && echo "✅ 内核模块已加载"

echo ""
echo "=========================================="
echo " 3. 启动 Minikube"
echo "=========================================="
if minikube status 2>/dev/null | grep -q "Running"; then
    echo "✅ Minikube 已在运行,跳过启动。"
else
    minikube start --driver=docker \
        --memory="${MINIKUBE_MEMORY}" \
        --cpus="${MINIKUBE_CPUS}" \
        --kubernetes-version="${K8S_VERSION}" \
        --cni="${CNI_PLUGIN}" \
        --docker-env=HTTP_PROXY="${PROXY_URL}" \
        --docker-env=HTTPS_PROXY="${PROXY_URL}" \
        --docker-env=NO_PROXY="${NO_PROXY_LIST}"
fi

echo ""
echo "=========================================="
echo " 4. 配置 containerd 代理"
echo "=========================================="
minikube ssh "sudo mkdir -p /etc/systemd/system/containerd.service.d/ && \
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf > /dev/null <<EOF
[Service]
Environment=\"HTTP_PROXY=${PROXY_URL}\"
Environment=\"HTTPS_PROXY=${PROXY_URL}\"
Environment=\"NO_PROXY=${NO_PROXY_LIST}\"
EOF
sudo systemctl daemon-reload && \
sudo systemctl restart containerd" && echo "✅ containerd 代理已配置"

echo ""
echo "=========================================="
echo " 5. 等待节点就绪"
echo "=========================================="
minikube kubectl -- wait --for=condition=Ready node/minikube --timeout=180s

echo ""
echo "=========================================="
echo " 6. 集群状态"
echo "=========================================="
minikube kubectl -- get nodes
echo ""
minikube kubectl -- get po -A

echo ""
echo "🎉 启动完成!"
echo ""
echo "=========================================="
echo " 访问应用:hello-minikube"
echo "=========================================="
echo "  # 虚拟机终端(保持运行)"
echo "  minikube kubectl -- port-forward service/hello-minikube 8080:8080 --address 0.0.0.0"
echo ""
echo "  # 宿主机终端(保持运行)"
echo "  ssh -L 8080:127.0.0.1:8080 ${VM_USER}@${VM_IP}"
echo ""
echo "  # 浏览器访问"
echo "  http://127.0.0.1:8080"
echo ""
echo "=========================================="
echo " 访问 Dashboard"
echo "=========================================="
echo "  # 虚拟机终端(保持运行)"
echo "  minikube kubectl -- port-forward -n kubernetes-dashboard service/kubernetes-dashboard 8443:80 --address 0.0.0.0"
echo ""
echo "  # 宿主机终端(保持运行)"
echo "  ssh -L 8443:127.0.0.1:8443 ${VM_USER}@${VM_IP}"
echo ""
echo "  # 浏览器访问"
echo "  http://127.0.0.1:8443"
echo ""
echo "  # 如果要求 Token,在虚拟机终端执行"
echo "  minikube kubectl -- -n kubernetes-dashboard create token kubernetes-dashboard"

终极成功配置(可直接复制)

历经九九八十一难,最终成功启动的命令如下(请替换你的代理 IP 和虚拟机 IP):

minikube delete
sudo rm -rf ~/.minikube

# 加载内核模块
sudo modprobe br_netfilter
sudo modprobe overlay

# 启动命令
minikube start --driver=docker --memory=4096 --cpus=2 \
  --kubernetes-version=v1.30.0 \
  --cni=flannel \
  --docker-env=HTTP_PROXY=http://192.168.65.1:7890 \
  --docker-env=HTTPS_PROXY=http://192.168.65.1:7890 \
  --docker-env=NO_PROXY=localhost,127.0.0.1,192.168.49.0/24,10.96.0.0/12,10.244.0.0/16

配置永久生效(写入 .bashrc)

避免每次重开终端 kubectl 被代理拦截:

echo 'export NO_PROXY=localhost,127.0.0.1,192.168.49.0/24,10.96.0.0/12,10.244.0.0/16' >> ~/.bashrc
echo 'export no_proxy=localhost,127.0.0.1,192.168.49.0/24,10.96.0.0/12,10.244.0.0/16' >> ~/.bashrc
echo 'alias kubectl="minikube kubectl --"' >> ~/.bashrc
source ~/.bashrc

内核模块开机自动加载:

echo -e "br_netfilter\noverlay" | sudo tee /etc/modules-load.d/k8s.conf

验证集群状态

x12@chenjx12:~$ kubectl get nodes
NAME       STATUS   ROLES           AGE    VERSION
minikube   Ready    control-plane   109s   v1.30.0

x12@chenjx12:~$ kubectl get po -A
NAMESPACE      NAME                               READY   STATUS    RESTARTS   AGE
kube-flannel   kube-flannel-ds-qdlmg              1/1     Running   0          93s
kube-system    coredns-7db6d8ff4d-9d7c7           1/1     Running   0          93s
kube-system    etcd-minikube                      1/1     Running   0          107s
kube-system    kube-apiserver-minikube            1/1     Running   0          107s
kube-system    kube-controller-manager-minikube   1/1     Running   0          107s
kube-system    kube-proxy-gvdsp                   1/1     Running   0          93s
kube-system    kube-scheduler-minikube            1/1     Running   0          107s
kube-system    storage-provisioner                1/1     Running   0          105s

当 minikube 节点显示 Ready,且 kube-flannel、coredns 等全部 Running 时,大功告成!


血泪总结

  1. 代理才是王道:在有稳定宿主机代理的情况下,千万不要画蛇添足用国内镜像源参数,官方源 + 代理是最稳的。
  2. 内存要留足:Kubernetes 本身很吃资源,宿主机虚拟机内存至少 8G 起步,Minikube 内部限制 4G,给系统留足余量。
  3. NO_PROXY 绝不能少:一定要把 Kubernetes 的集群内部网段(192.168.49.0/24、10.96.0.0/12、10.244.0.0/16)放入 NO_PROXY,否则 kubectl 会因为走了代理而连不上集群。
  4. 内核模块要加载:Ubuntu 22.04 宿主机运行容器网络前,一定要 modprobe br_netfilter 和 overlay。
  5. 别死磕 kindnet:在 Docker 驱动下遇到网络问题,果断换成 --cni=flannel,瞬间海阔天空。
  6. minikube image load 的欺骗性:它把镜像加载到了 Minikube 内部的 Docker 层,而 K8s 用的是 containerd。必须用 minikube cp + ctr -n k8s.io images import 才能让 Pod 真正找到镜像。
  7. imagePullPolicy 与 sha256 摘要:如果手动导入了镜像,记得把 Deployment 里的 image 去掉 @sha256:... 并设置 imagePullPolicy: IfNotPresent,否则会报 ErrImageNeverPull。
  8. 无图形界面访问 Dashboard:在 Server 版中,最佳的访问方式是“虚拟机端口转发 + 宿主机 SSH 隧道”,用宿主机浏览器访问 http://127.0.0.1:8443。
  9. containerd 代理隔离:--docker-env 只对 Docker 生效,Pod 拉取镜像时走的是 containerd。遇到应用镜像 ImagePullBackOff,要么手动 ctr 导入,要么单独给 containerd 配代理。

祝各位在 K8s 的海洋里少踩坑,多捞鱼!