当第一次在CentOS 7上尝试用kubeadm搭建Kubernetes 1.18集群时,我仿佛走进了一个布满暗礁的技术迷宫。每次看似简单的命令背后都可能隐藏着意想不到的陷阱——从系统配置的细微差别到版本兼容的魔鬼细节,每一步都可能让新手开发者陷入数小时的调试泥潭。这份指南不同于常规安装教程,它将带你穿越那些最容易让人跌倒的技术深坑,用实战经验为你铺平道路。
在虚拟机或物理机上安装CentOS 7后,大多数人会直接开始Kubernetes组件的安装,却不知系统层面的几个关键配置将决定后续所有操作的成败。
执行free -m查看内存时,如果看到swap分区仍有数值,说明简单的swapoff -a可能不够彻底。真正持久的解决方案需要两步:
bash复制# 临时关闭swap
swapoff -a
# 永久禁用(需编辑fstab文件)
sed -i '/swap/s/^/#/' /etc/fstab
注意:仅注释fstab还不够,必须重启后再次确认swap是否完全禁用。我曾遇到服务器重启后swap自动重新挂载的情况,最终发现是某些云平台的自定义服务在作祟。
很多教程会建议完全禁用SELinux,但在某些生产环境中这可能带来安全隐患。更优雅的做法是:
bash复制# 查看当前状态
getenforce
# 设置为permissive模式(记录但不阻止违规操作)
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
这种配置既避免了SELinux导致的权限问题,又保留了安全审计能力。当遇到容器无法访问宿主机文件时,可检查/var/log/audit/audit.log获取具体拦截信息。
以下参数必须设置,否则后续网络插件会无法正常工作:
bash复制cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 立即生效
sysctl --system
常见错误是只设置了前两个参数而忽略了ip_forward,这会导致Node间网络通信失败。用sysctl -a | grep forward验证配置是否生效。
Kubernetes生态中,版本间的微妙差异常常成为最大的绊脚石。特别是当混合使用不同来源的安装包时。
下表展示了Kubernetes 1.18支持的Docker版本范围:
| Kubernetes版本 | 支持的Docker版本范围 |
|---|---|
| 1.18.x | 18.06.x, 18.09.x, 19.03.x |
使用阿里云镜像安装指定版本的Docker CE:
bash复制# 添加阿里云Docker仓库
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 列出可用版本
yum list docker-ce --showduplicates | sort -r
# 安装特定版本(例如19.03.15)
yum install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io
我曾因直接安装最新版Docker导致与kubelet不兼容,集群持续处于崩溃状态。教训是:永远先查版本兼容矩阵。
安装kubelet、kubeadm和kubectl时,必须明确指定相同版本:
bash复制# 添加阿里云Kubernetes仓库
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
EOF
# 安装指定版本(注意版本号完全一致)
yum install -y kubelet-1.18.20 kubeadm-1.18.20 kubectl-1.18.20
关键细节:即使后续
kubeadm init指定了版本,如果已安装的kubelet版本不一致,初始化仍会失败。错误信息可能很隐晦,例如"kubelet isn't running or healthy"。
执行kubeadm init看似简单,但实际环境中总会遇到各种意外情况。
当使用默认仓库时,国内用户常遇到镜像拉取超时。虽然--image-repository参数可以指定阿里云镜像,但某些次要镜像仍可能拉取失败。完整的解决方案是:
bash复制# 预先拉取所有所需镜像
kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers
# 初始化命令示例
kubeadm init \
--kubernetes-version=v1.18.20 \
--apiserver-advertise-address=192.168.1.100 \
--image-repository=registry.aliyuncs.com/google_containers \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
如果仍有个别镜像缺失,可以手动拉取并重打标签:
bash复制docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.18.20
docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.18.20 k8s.gcr.io/kube-apiserver:v1.18.20
kubeadm init生成的加入令牌默认24小时过期。生产环境中更可靠的做法是:
bash复制# 创建永久令牌
kubeadm token create --ttl 0
# 获取CA证书哈希(当忘记保存初始化时的加入命令时)
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
将生成的令牌和哈希值妥善保存,后续节点加入时使用:
bash复制kubeadm join <control-plane-host>:<control-plane-port> \
--token <token> \
--discovery-token-ca-cert-hash sha256:<hash>
集群初始化成功只是第一步,网络插件安装和节点管理才是真正的挑战开始。
官方提供的Calico manifest可能需要针对特定环境调整:
bash复制# 下载原始文件
wget https://docs.projectcalico.org/manifests/calico.yaml
# 修改Pod CIDR以匹配初始化时的设置(搜索192.168.0.0/16替换为自己的配置)
sed -i 's/192.168.0.0/10.244.0.0/g' calico.yaml
# 部署Calico
kubectl apply -f calico.yaml
常见问题排查命令:
bash复制# 检查Calico Pod状态
kubectl get pods -n kube-system -l k8s-app=calico-node
# 查看具体错误日志
kubectl logs -n kube-system <calico-pod-name>
当worker节点执行kubeadm join失败时,按以下步骤排查:
检查基础连通性:
bash复制ping <master-ip>
telnet <master-ip> 6443
验证证书时间:
bash复制# 在所有节点执行,时间差异不能超过几分钟
date
检查防火墙规则:
bash复制# 临时关闭防火墙测试
systemctl stop firewalld
我曾遇到节点时间不同步导致证书验证失败的情况,表面报错却是"connection refused",浪费了数小时才定位到真正原因。
即使集群正常运行后,仍可能遇到各种奇怪现象。以下是几个典型案例:
当kubectl get nodes显示节点NotReady时:
bash复制# 1. 检查kubelet状态
systemctl status kubelet
# 2. 查看kubelet日志
journalctl -u kubelet -n 100 --no-pager
# 3. 检查容器运行时
docker ps -a | grep pause
常见原因包括:
Kubernetes集群证书默认有效期为1年。提前检查证书有效期:
bash复制openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep Not
续期所有证书(在master节点执行):
bash复制kubeadm alpha certs renew all
记得更新kubeconfig文件:
bash复制cp /etc/kubernetes/admin.conf $HOME/.kube/config
Kubernetes Dashboard的安装看似简单,却有几个关键注意点:
编辑recommended.yaml,将所有k8s.gcr.io镜像替换为阿里云镜像:
bash复制sed -i 's/k8s.gcr.io/registry.aliyuncs.com\/google_containers/g' recommended.yaml
修改Service部分为NodePort并添加安全端口:
yaml复制kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
nodePort: 30443
selector:
k8s-app: kubernetes-dashboard
安全提示:不要使用30000-32767外的端口,某些云平台会默认屏蔽这些端口。
创建管理员ServiceAccount:
yaml复制cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
EOF
获取访问令牌:
bash复制kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')