很多刚接触Kubernetes的开发者都会有个疑问:既然云厂商提供了现成的K8S服务,为什么还要在本地折腾单机版?我刚开始学习容器编排时也这么想过,直到在实际项目中踩了几个坑才明白本地环境的重要性。
单机版K8S最核心的价值在于零成本搭建开发测试环境。想象一下,你正在开发一个微服务应用,每次修改代码后都要推到云端验证,光是等待集群响应和镜像构建的时间就让人抓狂。而在本地笔记本或开发机上运行的轻量级K8S,就像随身携带的瑞士军刀,能快速验证Pod配置、Service路由等基础功能。我团队里有个新人曾用Minikube在咖啡厅调试完整个订单服务的灰度发布逻辑,这种效率是云环境难以比拟的。
另一个容易被忽视的优势是学习曲线的平滑过渡。全功能的K8S集群涉及网络插件、存储供应等复杂概念,而单机版把复杂度控制在合理范围。比如用kubeadm搭建的环境,既保留了核心API对象的使用体验,又免去了多节点网络配置的烦恼。记得我第一次成功在单节点上跑通StatefulSet时,那种"原来如此"的顿悟感至今难忘。
对于中小型项目,单机K8S还能作为持续集成流水线的廉价测试床。GitLab Runner配置一个Shell执行器,配合本地K8S集群就能实现代码提交后自动部署验收环境。我们内部有个数据清洗工具链,就是用这种方式实现了分钟级的端到端测试反馈。
原始文章提到要关闭SELinux和防火墙,这在学习环境没问题,但实际我会建议更精细化的配置。比如用以下命令临时设置SELinux为permissive模式而非完全禁用:
bash复制sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
防火墙方面,其实可以只开放K8S所需端口。以下是我在CentOS 8上验证过的firewalld规则:
bash复制sudo firewall-cmd --permanent --add-port=6443/tcp # API Server
sudo firewall-cmd --permanent --add-port=10250/tcp # Kubelet
sudo firewall-cmd --permanent --add-port=8472/udp # Flannel VXLAN
sudo firewall-cmd --reload
内存和交换分区配置是另一个常见坑点。K8S默认要求关闭swap,但对于资源紧张的开发机,可以通过kubelet参数妥协:
bash复制sudo sed -i 's/^GRUB_CMDLINE_LINUX="/&swapaccount=1 /' /etc/default/grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
然后在kubelet配置中添加:
yaml复制apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
failSwapOn: false
虽然Docker仍是主流选择,但我建议新项目直接使用containerd。它作为K8S官方推荐的运行时,资源占用更少且更稳定。安装步骤比原始文章更简洁:
bash复制cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 安装containerd
sudo yum install -y containerd.io
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
国内用户记得配置镜像加速。这是我收集的几个可用源:
toml复制[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
endpoint = ["https://gcr.mirrors.ustc.edu.cn"]
原始文章手动安装各组件的方式已过时,现在主流都用kubeadm。以下是经过数十次验证的可靠步骤:
bash复制# 安装工具链
sudo yum install -y kubelet-1.23.8 kubeadm-1.23.8 kubectl-1.23.8 --disableexcludes=kubernetes
# 初始化控制平面(单节点模式)
sudo kubeadm init \
--pod-network-cidr=10.244.0.0/16 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.23.8
# 配置kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
遇到证书问题时,可以尝试这个黑科技(仅限开发环境):
bash复制sudo rm -rf /etc/kubernetes/pki/apiserver.*
sudo kubeadm init phase certs all --apiserver-advertise-address 0.0.0.0
Flannel是最简单的选择,但对于想体验高级功能的开发者,Calico更值得尝试:
bash复制kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
如果遇到网络不通,用这个诊断命令:
bash复制kubectl get pods -n kube-system -o wide
kubectl logs -n kube-system <pod-name>
原始文章中的mysql-rc.yaml已经过时,现在推荐使用Deployment:
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "yourpassword"
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
hostPath:
path: /data/mysql
暴露服务的正确姿势:
yaml复制apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
type: NodePort
镜像拉取失败时,试试这个技巧:
bash复制kubectl get events --sort-by=.metadata.creationTimestamp
对于一直ContainerCreating的Pod,用describe命令深挖:
bash复制kubectl describe pod <pod-name>
我曾遇到过一个诡异问题:Pod始终无法调度,最后发现是node标签缺失。修复方法:
bash复制kubectl label nodes <your-node-name> kubernetes.io/role=worker
持久化存储权限问题也很常见,这个命令能快速修复:
bash复制sudo chmod -R 777 /data/mysql