CentOS7裸机部署K8s集群实战:Kubeadm+Containerd最新1.27版完整教程
从裸机到生产就绪:CentOS 7上构建Kubernetes 1.27高可用集群的深度实践
如果你正带领团队从零开始构建私有化容器平台,或者希望摆脱对公有云托管K8s服务的依赖以优化长期成本,那么这篇基于物理服务器或虚拟化环境的实战指南,正是为你准备的。我们将一起走过从CentOS 7裸机初始化,到使用Kubeadm 1.27和Containerd搭建一个稳定、可维护的生产级Kubernetes集群的完整旅程。这不仅仅是步骤的罗列,更会深入每个关键决策背后的考量,比如为何在当下选择Containerd而非Docker,如何为国内网络环境优化镜像拉取,以及如何规避那些让新手头疼的“坑”。整个过程,我们假设你拥有三台CentOS 7服务器(或虚拟机),并准备好将它们转化为一个协同工作的现代化应用编排平台。
1. 基石:生产环境下的系统初始化与内核调优
在安装任何Kubernetes组件之前,我们必须确保底层操作系统是一个稳定、合规的基石。很多部署失败的根本原因,都源于此阶段的疏忽。
1.1 网络与身份标识的固化
在生产环境中,动态IP地址是灾难的源头。我们需要为每台服务器配置静态IP。以主节点(假设网卡为ens192)为例,编辑网络配置文件:
vi /etc/sysconfig/network-scripts/ifcfg-ens192关键配置项修改如下:
BOOTPROTO=static ONBOOT=yes IPADDR=192.168.1.100 # 根据你的实际规划填写 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 DNS1=114.114.114.114注意:
UUID和DEVICE等字段需保持与原有配置一致。修改后,使用systemctl restart network重启网络服务。
接下来,为集群中的每个节点设置唯一的主机名,并建立主机名解析。这能极大提升后续运维的便利性。
# 在主节点执行 hostnamectl set-hostname k8s-master-01 # 在工作节点1执行 hostnamectl set-hostname k8s-worker-01 # 在工作节点2执行 hostnamectl set-hostname k8s-worker-02然后,在所有三台服务器的/etc/hosts文件中添加以下记录,确保它们能通过主机名相互通信:
192.168.1.100 k8s-master-01 192.168.1.101 k8s-worker-01 192.168.1.102 k8s-worker-02为了方便在主节点上管理整个集群,配置SSH免密登录到所有节点是个好习惯。在主节点上生成密钥对,并分发公钥:
ssh-keygen -t rsa -b 4096 -N "" -f ~/.ssh/id_rsa ssh-copy-id root@k8s-master-01 ssh-copy-id root@k8s-worker-01 ssh-copy-id root@k8s-worker-021.2 内核参数与安全策略调整
Kubernetes对Linux内核有一些特定要求。首先,我们需要加载br_netfilter模块,并调整相关网络参数。
# 加载模块 modprobe br_netfilter # 确保开机自动加载 echo 'br_netfilter' > /etc/modules-load.d/k8s.conf # 配置网络桥接和转发参数 cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF # 使配置生效 sysctl --system关闭Swap是Kubernetes的强制要求,因为kubelet需要确保Pod的内存请求得到保障,而非被交换到磁盘上,否则会导致性能和稳定性问题。
# 临时关闭 swapoff -a # 永久关闭:注释掉/etc/fstab中所有包含swap的行 sed -i '/swap/s/^/#/' /etc/fstab对于防火墙和SELinux,在学习和测试环境中,通常选择关闭以简化问题。但在严格的生产环境中,更推荐的是配置精确的防火墙规则和SELinux策略。这里我们采用折中方案:
# 关闭防火墙(生产环境建议配置具体规则) systemctl stop firewalld && systemctl disable firewalld # 关闭SELinux(生产环境建议设置为permissive模式并配置策略) setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config最后,确保所有节点时间同步。集群内时间不一致会导致证书验证、事件排序等一系列问题。
yum install -y ntpdate ntpdate time.windows.com # 写入定时任务,每半小时同步一次 echo "*/30 * * * * /usr/sbin/ntpdate time.windows.com > /dev/null 2>&1" | crontab -2. 容器运行时抉择:全面拥抱Containerd
自Kubernetes 1.24版本起,Dockershim已被移除,这意味着K8s不再直接支持Docker作为运行时。Containerd成为了事实上的标准选择。它更轻量、更专注,直接实现了Kubernetes容器运行时接口(CRI)。
2.2 Containerd的安装与深度配置
我们将通过阿里云镜像源安装指定版本的Containerd。
# 配置Docker CE仓库(Containerd包在其中) yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 安装指定版本的containerd.io yum install -y containerd.io-1.6.21安装完成后,生成默认配置文件并进行关键修改:
# 生成默认配置 containerd config default > /etc/containerd/config.toml使用vi /etc/containerd/config.toml编辑配置文件,找到并修改以下两处:
- 将
SystemdCgroup从false改为true。这确保Containerd使用systemd作为cgroup驱动,与kubelet保持一致。 - 将
sandbox_image指向国内可访问的镜像地址,解决pause镜像拉取失败的问题:sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
接下来,配置镜像加速器。这对于在国内快速拉取Docker Hub上的公共镜像至关重要。
mkdir -p /etc/containerd/certs.d/docker.io创建并编辑/etc/containerd/certs.d/docker.io/hosts.toml文件:
[host."https://<你的镜像加速器地址>.mirror.aliyuncs.com"] capabilities = ["pull", "resolve"]提示:请将
<你的镜像加速器地址>替换为你从阿里云容器镜像服务获取的实际加速器地址。
最后,启动并设置Containerd开机自启:
systemctl daemon-reload systemctl enable --now containerd验证安装:运行ctr version和crictl version,应能正确输出版本信息。
3. Kubeadm集群部署:从初始化到节点扩容
3.1 安装Kubernetes核心组件
配置Kubernetes的阿里云Yum源,然后安装指定版本的三件套(kubeadm, kubelet, kubectl)。
cat > /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled=1 gpgcheck=0 EOF # 在所有节点安装1.27.0版本 yum install -y kubelet-1.27.0 kubeadm-1.27.0 kubectl-1.27.0 systemctl enable kubelet # 注意:此时先不启动kubelet3.2 主节点初始化:定制化配置是关键
直接使用kubeadm init虽然简单,但使用配置文件能提供更精细的控制。我们先导出默认配置:
kubeadm config print init-defaults > kubeadm-config.yaml然后编辑这个kubeadm-config.yaml文件,以下是一些必须和推荐的修改项:
apiVersion: kubeadm.k8s.io/v1beta3 kind: InitConfiguration localAPIEndpoint: advertiseAddress: 192.168.1.100 # 主节点的IP bindPort: 6443 nodeRegistration: criSocket: unix:///var/run/containerd/containerd.sock # 指定Containerd的socket路径 imagePullPolicy: IfNotPresent name: k8s-master-01 # 主节点主机名 --- apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: 1.27.0 imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers # 使用阿里云镜像仓库 networking: podSubnet: 172.16.0.0/16 # 设置Pod网络CIDR,需与后续网络插件匹配 serviceSubnet: 10.96.0.0/12 --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd # 必须与Containerd配置一致现在,执行初始化命令。--ignore-preflight-errors=Swap参数是因为我们已关闭Swap,但检查可能仍会警告。
kubeadm init --config=kubeadm-config.yaml --ignore-preflight-errors=Swap这个过程会拉取镜像、生成证书、启动控制平面组件。成功后会输出类似以下的提示:
Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.1.100:6443 --token <token> \ --discovery-token-ca-cert-hash sha256:<hash>请务必保存好最后的kubeadm join命令,用于工作节点加入。接着,按照提示配置kubectl:
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config3.3 工作节点加入集群
在每个工作节点上,确保已完成第1章和第2章的所有系统初始化、Containerd安装和Kubernetes组件安装。然后,直接运行主节点初始化成功后给出的kubeadm join命令。
加入成功后,在主节点执行kubectl get nodes,可以看到新加入的节点状态为NotReady,这是因为尚未安装网络插件。
4. 网络、观测与生产加固
4.1 安装Calico网络插件
Pod之间要能通信,必须安装CNI(容器网络接口)插件。Calico是性能和生产特性都非常优秀的选择。我们安装与其operator部署方式,这比直接应用YAML更易于管理。
首先,安装Calico的CLI工具(tigera-operator)和自定义资源定义(CRD):
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml然后,下载并定制安装清单。我们需要确保Pod网段与初始化时设置的podSubnet(172.16.0.0/16)一致。
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml -O编辑custom-resources.yaml文件,确认cidr字段:
apiVersion: operator.tigera.io/v1 kind: Installation metadata: name: default spec: calicoNetwork: ipPools: - blockSize: 26 cidr: 172.16.0.0/16 # 必须与kubeadm配置一致 encapsulation: VXLANCrossSubnet natOutgoing: Enabled nodeSelector: all() --- apiVersion: operator.tigera.io/v1 kind: APIServer metadata: name: default spec: {}应用这个配置:
kubectl create -f custom-resources.yaml等待几分钟,使用kubectl get pods -n calico-system查看所有Pod是否都变为Running状态。同时,kubectl get nodes应显示所有节点状态为Ready。
4.2 基础功能验证与核心组件探秘
集群就绪后,我们进行几个关键测试。
1. 核心DNS解析测试:CoreDNS是集群内部服务发现的核心。创建一个临时Pod测试其功能:
kubectl run dns-test --image=busybox:1.36 --restart=Never --rm -it -- sh # 进入Pod后执行 nslookup kubernetes.default如果成功返回kubernetes.default.svc.cluster.local的IP地址(通常是10.96.0.1),说明CoreDNS工作正常。
2. 跨节点Pod网络测试:在不同节点上部署两个Pod,并互相ping通,可以验证Calico网络策略和跨主机通信。
# 在节点1(通过节点选择器) kubectl run ping-source --image=alpine --restart=Never --labels=app=pingtest --overrides='{"spec": {"nodeName": "k8s-worker-01"}}' -- sleep 3600 # 在节点2 kubectl run ping-target --image=alpine --restart=Never --labels=app=pingtest --overrides='{"spec": {"nodeName": "k8s-worker-02"}}' -- sleep 3600 # 获取Pod IP TARGET_IP=$(kubectl get pod ping-target -o jsonpath='{.status.podIP}') # 从源Pod ping 目标Pod kubectl exec ping-source -- ping -c 3 $TARGET_IP4.3 生产环境考量与常见故障排查
证书管理:Kubeadm默认生成的证书有效期为一年。在过期前,需要使用kubeadm certs renew all进行更新。建议将此纳入日常运维监控。
资源预留:为Kubernetes系统组件(kubelet、kube-proxy等)和操作系统预留足够的内存和CPU,防止因资源竞争导致节点不稳定。这可以通过kubelet的--system-reserved和--kube-reserved参数配置。
日志与监控:生产集群必须建立完善的日志收集(如EFK Stack:Elasticsearch, Fluentd, Kibana)和监控体系(如Prometheus + Grafana)。从部署第一天起,就应规划这些可观测性组件的部署。
遇到节点NotReady?按以下思路排查:
journalctl -u kubelet -f查看kubelet日志,寻找错误信息。crictl ps检查容器运行时是否正常。- 确认网络插件(Calico)的Pod是否全部运行正常:
kubectl get pods -n calico-system。 - 检查节点资源(内存、磁盘)是否耗尽。
镜像拉取失败:这是国内环境最常见的问题。确保:
- Containerd配置了正确的镜像加速器。
- 对于
k8s.gcr.io等国外镜像,在kubeadm-config.yaml中已配置imageRepository为阿里云镜像仓库。 - 对于自定义部署的Pod,可以在Pod Spec中指定
imagePullSecrets或使用国内镜像仓库。
从三台裸机CentOS服务器到一个功能完整的Kubernetes 1.27集群,我们一步步搭建并验证了其核心功能。选择Containerd、细致的内核调优、清晰的网络规划以及利用国内镜像源加速,这些决策共同构成了一个适合本地化生产环境的基础。然而,这仅仅是起点。接下来,你需要考虑持久化存储(如Ceph RBD、NFS CSI)、负载均衡器(如MetalLB)、安全策略(Pod Security Standards, NetworkPolicy)以及CI/CD流水线的集成。记住,在生产环境中,变更管理、备份恢复计划和灾难恢复演练与集群搭建本身同等重要。每一次kubectl apply的背后,都应对其影响有充分的理解。
