当前位置: 首页 > news >正文

CentOS 7上Kubernetes 1.20集群部署全攻略:从零搭建到避坑指南

1. 项目概述:在CentOS 7上搭建Kubernetes 1.20集群

如果你正在寻找一份能在生产环境或学习环境中,手把手指导你在CentOS 7系统上部署一个稳定、可用的Kubernetes 1.20集群的详细指南,那么你来对地方了。Kubernetes,也就是大家常说的k8s,已经成为容器编排领域的事实标准,但对于很多刚接触的开发者或运维工程师来说,从零开始搭建一个集群依然是个不小的挑战,尤其是在相对“古老”但依然广泛使用的CentOS 7系统上。这个过程涉及到系统配置、容器运行时安装、核心组件部署、网络插件集成等多个环节,任何一个步骤的疏漏都可能导致集群初始化失败或运行异常。

我结合自己多次在CentOS 7上部署k8s 1.20版本的经验,将整个流程拆解成清晰、可复现的步骤。这篇文章不仅会告诉你“怎么做”,更会解释“为什么这么做”,比如为什么必须关闭Swap,为什么Docker的cgroup驱动最好用systemd,以及遇到镜像拉取失败、节点状态NotReady等常见问题时该如何排查。无论你是为了搭建开发测试环境,还是为生产部署做准备,这份指南都能帮你避开我踩过的那些坑,高效地完成集群搭建。

2. 环境准备与前置条件解析

在开始敲命令之前,充分的准备工作是成功的一半。对于Kubernetes集群部署,我们需要从硬件资源、网络规划、系统版本等多个维度进行考量,确保基础环境满足要求。

2.1 硬件与节点规划

一个最小化的、可用于学习和功能验证的Kubernetes集群至少需要两台机器:一个控制平面节点和一个工作节点。但为了体验高可用和更好的隔离性,我建议使用三台节点,结构如下:

  • 控制平面节点:1台。负责集群的管理和控制,运行kube-apiserverkube-schedulerkube-controller-manageretcd等核心组件。在生产环境中,为了实现高可用,控制平面通常需要3台或更多奇数台机器。
  • 工作节点:2台。负责运行实际的应用容器负载。

每台机器的最低配置建议:

  • CPU:2核或以上。控制平面节点需要更多计算资源来处理调度和API请求。
  • 内存:2GB或以上,建议4GB。内存不足会导致kubeletdocker进程被系统杀死。
  • 磁盘:20GB或以上。需要预留空间存放容器镜像、etcd数据以及日志。
  • 网络:所有节点必须在同一个二层网络内,能够通过IP互相通信,且主机名可以正确解析。

在我的实验环境中,使用了三台虚拟机,具体信息如下表:

主机名IP地址角色操作系统
k8s-master192.168.110.130Control Plane, MasterCentOS 7.9
k8s-node1192.168.110.129WorkerCentOS 7.9
k8s-node2192.168.110.128WorkerCentOS 7.9

注意:确保你的防火墙(如firewalld)或安全组规则放行了Kubernetes所需的端口,最关键的包括6443(API Server)、10250(kubelet API)、2379-2380(etcd)等。一个简单的做法是在测试环境暂时将防火墙默认区域设置为trusted,但生产环境务必配置精确的规则。

2.2 操作系统统一配置

以下操作需要在所有节点上执行,以确保环境一致性。

2.2.1 设置主机名与Hosts解析

为每个节点设置唯一的主机名,并配置/etc/hosts文件,让节点之间可以通过主机名互相访问。这能避免后续很多因网络解析问题导致的诡异错误。

# 在k8s-master节点上执行 hostnamectl set-hostname k8s-master # 在k8s-node1上执行 hostnamectl set-hostname k8s-node1 # 在k8s-node2上执行 hostnamectl set-hostname k8s-node2 # 编辑所有节点的 /etc/hosts 文件,添加以下内容 cat >> /etc/hosts << EOF 192.168.110.130 k8s-master 192.168.110.129 k8s-node1 192.168.110.128 k8s-node2 EOF

配置完成后,可以互相ping一下主机名,测试解析是否正常。

2.2.2 关闭Swap并禁用SELinux

这是Kubernetes的强制要求。Swap的存在会影响kubelet对节点内存使用情况的判断,可能导致Pod调度和运行出现问题。kubeadm在初始化时会直接检查Swap是否关闭,如果未关闭则会报错并中止。

# 临时关闭当前已启用的Swap swapoff -a # 永久关闭,注释或删除 /etc/fstab 中所有包含swap的行 sed -i '/swap/s/^/#/' /etc/fstab # 临时将SELinux设置为permissive模式 setenforce 0 # 永久禁用SELinux sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config

SELinux在某些安全要求严格的场景下需要保持开启并配置正确的策略,但对于学习和测试环境,禁用它可以避免很多权限相关的复杂问题。

2.2.3 配置内核参数与加载模块

Kubernetes需要一些特定的内核参数来支持网络转发和网桥过滤。编辑/etc/sysctl.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

这里net.ipv4.ip_forward = 1开启了IPv4转发,这是容器跨节点通信的基础。bridge-nf-call-iptables参数是为了让网桥上的流量也经过iptables规则,这是Calico、Flannel等CNI插件正常工作所必需的。

2.2.4 配置时间同步

集群内所有节点的时间必须同步,否则会导致证书错误、日志时间错乱等一系列问题。使用chronydntpd服务进行时间同步。

# 安装chrony yum install -y chrony # 启动并设置开机自启 systemctl enable --now chronyd # 检查时间同步状态 chronyc sources -v

3. 容器运行时与Kubernetes组件安装

Kubernetes本身不直接运行容器,它通过CRI接口与容器运行时交互。虽然Kubernetes 1.20版本已经宣布弃用Docker,但通过cri-dockerd适配器,我们依然可以使用熟悉的Docker作为运行时。这里我们选择安装Docker,因为它生态成熟,资料丰富。

3.1 在所有节点安装Docker

首先配置Docker的yum源,然后安装指定版本。不推荐使用系统默认源里过旧的版本。

# 安装yum工具包并设置Docker仓库 yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 安装Docker CE(社区版)及命令行工具 yum install -y docker-ce docker-ce-cli containerd.io # 启动Docker并设置开机自启 systemctl enable --now docker

安装完成后,验证Docker版本并测试运行一个hello-world容器:docker run --rm hello-world。如果成功,说明Docker安装正确。

接下来是关键一步:配置Docker使用systemd作为cgroup驱动。Kubernetes默认使用systemd作为cgroup驱动,如果Docker使用cgroupfs,会导致kubelet启动失败。编辑/etc/docker/daemon.json文件(如果不存在则创建):

{ "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "registry-mirrors": ["https://<你的镜像加速器地址>.mirror.aliyuncs.com"] }

其中,registry-mirrors可以替换为阿里云、腾讯云等提供的国内镜像加速地址,能极大提升拉取镜像的速度。配置完成后,重启Docker:systemctl restart docker。使用docker info | grep Cgroup命令确认驱动已改为systemd

3.2 安装kubeadm, kubelet和kubectl

kubeadm是官方推荐的集群引导工具;kubelet是运行在每个节点上的代理,负责管理Pod和容器;kubectl是命令行工具,用于与集群交互。我们需要在所有节点上安装它们。

由于官方源在国内访问较慢,我们使用阿里云的Kubernetes镜像源。

# 1. 添加阿里云Kubernetes Yum源 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=1 repo_gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF # 2. 安装指定版本(这里安装1.20.15,一个稳定的1.20子版本) yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15 --disableexcludes=kubernetes # 3. 设置kubelet开机自启(先不启动,等kubeadm init后再启动) systemctl enable kubelet

注意--disableexcludes=kubernetes参数是为了确保在安装时,即使系统有其他仓库排除了Kubernetes包,也能正常安装。此时先不要启动kubelet,因为它需要由kubeadm初始化后生成的配置文件才能正确运行。

4. 使用kubeadm初始化控制平面

准备工作就绪后,我们就可以在规划为Master的节点(k8s-master)上初始化控制平面了。这是搭建集群最核心的一步。

4.1 预拉取镜像与初始化命令

kubeadm init会拉取运行Kubernetes控制平面所需的所有镜像。由于网络原因,直接从k8s.gcr.io拉取很可能失败。我们可以使用阿里云镜像仓库,并先手动拉取镜像,避免初始化过程因镜像问题中断。

# 在k8s-master节点上执行 # 查看kubeadm需要哪些镜像 kubeadm config images list --kubernetes-version v1.20.15 # 使用阿里云镜像仓库拉取镜像(这是一个常用技巧) docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.15 docker pull registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.15 docker pull registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.15 docker pull registry.aliyuncs.com/google_containers/kube-proxy:v1.20.15 docker pull registry.aliyuncs.com/google_containers/pause:3.2 docker pull registry.aliyuncs.com/google_containers/etcd:3.4.13-0 docker pull registry.aliyuncs.com/google_containers/coredns:1.7.0 # 为镜像打上符合kubeadm期望的标签 docker tag registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.15 k8s.gcr.io/kube-apiserver:v1.20.15 docker tag registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.15 k8s.gcr.io/kube-controller-manager:v1.20.15 # ... 其他镜像同理

完成镜像准备后,执行初始化命令。这里有几个重要参数需要解释:

  • --image-repository: 指定镜像仓库,我们使用阿里云仓库。
  • --kubernetes-version: 必须与安装的kubeadmkubelet版本严格一致,这里是v1.20.15
  • --pod-network-cidr: 设置Pod网络的IP地址段。这个网段不能与任何主机网络重叠。我们选择10.244.0.0/16,这是Flannel网络的默认网段,也与Calico的默认配置兼容。
  • --apiserver-advertise-address: 指定API Server对外公告的IP地址。如果你的Master节点有多个网卡,需要指定一个其他节点能访问到的IP。这里我们使用192.168.110.130
kubeadm init \ --image-repository=registry.aliyuncs.com/google_containers \ --kubernetes-version=v1.20.15 \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=192.168.110.130

执行这个命令后,kubeadm会进行一系列预检,生成证书和配置文件,最后启动控制平面的各个组件。整个过程大约需要1-3分钟。如果一切顺利,你会在最后看到类似下面的成功信息,其中包含加入集群的令牌命令:

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.110.130:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

4.2 配置kubectl并检查集群状态

根据上面的提示,我们需要配置kubectl的认证信息,这样才能以管理员身份操作集群。

mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config

现在,使用kubectl get nodes命令查看节点状态,应该能看到k8s-master节点,但其状态是NotReady。这是因为我们还没有安装Pod网络插件(CNI),集群内部的网络还不通。

[root@k8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master NotReady control-plane,master 2m v1.20.15

5. 部署Pod网络插件(CNI)与加入工作节点

Pod网络插件是Kubernetes集群的“神经系统”,负责为每个Pod分配IP地址,并实现Pod之间的跨节点通信。没有它,集群就无法正常工作。

5.1 部署Calico网络插件

CNI插件有很多选择,如Flannel、Calico、Cilium等。Calico以其高性能和强大的网络策略功能而闻名,我们选择它。首先,下载Calico的部署清单文件。

# 在k8s-master节点上执行 curl https://docs.projectcalico.org/manifests/calico.yaml -O

下载的calico.yaml文件里定义了所有需要的Kubernetes资源。我们需要修改一个关键配置,使其Pod网段与我们初始化时指定的--pod-network-cidr一致。找到文件中配置CALICO_IPV4POOL_CIDR环境变量的地方(大约在第1000行附近),将其值修改为10.244.0.0/16

# 搜索并修改这一行 - name: CALICO_IPV4POOL_CIDR value: "10.244.0.0/16"

修改完成后,应用这个清单文件:

kubectl apply -f calico.yaml

这个命令会创建一系列的资源,包括DaemonSetDeploymentServiceAccount等。稍等片刻,使用kubectl get pods -n kube-system命令查看calico-nodecalico-kube-controllers这两个Pod的状态,当它们都变成Running时,网络插件就部署成功了。此时再查看节点状态,k8s-master应该已经变为Ready

5.2 将工作节点加入集群

现在,回到初始化成功时输出的那行kubeadm join命令。将这条命令分别在k8s-node1k8s-node2上以root权限执行。

# 在 k8s-node1 和 k8s-node2 上分别执行 kubeadm join 192.168.110.130:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

如果令牌过期或丢失,可以在Master节点上使用kubeadm token create --print-join-command生成新的加入命令。

执行成功后,在Master节点上再次运行kubectl get nodes,你应该能看到三个节点都是Ready状态。

[root@k8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 15m v1.20.15 k8s-node1 Ready <none> 2m v1.20.15 k8s-node2 Ready <none> 1m v1.20.15

6. 集群验证与常用配置

集群搭建完成后,我们还需要进行一些验证和优化配置,确保其稳定可用。

6.1 基础功能验证

部署一个最简单的Nginx应用来测试集群是否正常工作。

# 1. 部署一个Nginx Deployment kubectl create deployment nginx --image=nginx:1.21-alpine # 2. 将Nginx服务暴露为NodePort类型 kubectl expose deployment nginx --port=80 --type=NodePort # 3. 查看Pod和服务状态 kubectl get pods,svc -l app=nginx

如果Pod状态为Running,并且SERVICE列显示了一个端口映射(如80:3xxxx/TCP),说明部署成功。你可以通过任意节点的IP地址和映射出的端口(如http://192.168.110.129:3xxxx)在浏览器中访问到Nginx的欢迎页面。

6.2 配置kubectl命令自动补全

为了提高使用kubectl的效率,强烈建议启用命令自动补全功能。

# 对于bash用户 echo 'source <(kubectl completion bash)' >> ~/.bashrc source ~/.bashrc # 对于zsh用户 echo 'source <(kubectl completion zsh)' >> ~/.zshrc source ~/.zshrc

配置后,输入kubectl get p然后按Tab键,会自动补全为kubectl get pods

6.3 移除Master节点的污点(Taint)

默认情况下,出于安全考虑,Master节点被设置了NoSchedule污点,普通Pod不会被调度到上面运行。对于资源有限的测试环境,你可能希望Master节点也能运行工作负载。

# 查看节点的污点 kubectl describe node k8s-master | grep Taints # 移除污点 kubectl taint nodes k8s-master node-role.kubernetes.io/master-

移除污点后,Master节点就可以像Worker节点一样接受Pod调度了。

7. 常见问题排查与避坑指南

即便按照步骤操作,你也可能会遇到一些问题。这里我总结几个最常见的“坑”及其解决方法。

问题一:kubeadm init时卡在[kubelet-check]或镜像拉取失败。

  • 原因:最常见的原因是网络问题,无法从指定仓库拉取镜像。
  • 解决
    1. 使用kubeadm config images pull --image-repository=registry.aliyuncs.com/google_containers预拉取镜像。
    2. 手动拉取并重命名镜像,如前面步骤所示。
    3. 检查Docker的cgroup驱动是否为systemd
    4. 确保Swap已关闭,使用free -h确认Swap行显示为0。

问题二:Worker节点加入集群失败,提示connection refused或证书错误。

  • 原因:Master节点的API Server(6443端口)无法访问,或者加入令牌过期。
  • 解决
    1. 检查Master节点的防火墙是否放行了6443端口:firewall-cmd --list-ports
    2. 在Master节点重新生成加入命令:kubeadm token create --print-join-command
    3. 检查/etc/hosts文件,确保Worker节点能正确解析Master的主机名和IP。

问题三:节点状态长时间为NotReady

  • 原因:几乎可以肯定是网络插件(CNI)没有正确安装或配置错误。
  • 解决
    1. 使用kubectl get pods -n kube-system检查calico-nodecoredns的Pod是否处于Running状态。如果不是,使用kubectl describe pod <pod-name> -n kube-systemkubectl logs <pod-name> -n kube-system查看详细错误信息。
    2. 确认calico.yaml中的CALICO_IPV4POOL_CIDR是否与kubeadm init时设置的--pod-network-cidr一致。
    3. 检查内核参数net.ipv4.ip_forwardnet.bridge.bridge-nf-call-iptables是否已设置为1。

问题四:使用kubectl命令时提示The connection to the server xxxx was refused

  • 原因kubectl没有正确的配置文件或API Server未启动。
  • 解决
    1. 确认已正确执行mkdir -p $HOME/.kubecp /etc/kubernetes/admin.conf $HOME/.kube/config
    2. 检查Master节点上kube-apiserver的Pod是否运行:kubectl get pods -n kube-system | grep apiserver

问题五:Pod一直处于Pending状态。

  • 原因:通常是没有节点满足调度条件,比如资源不足或节点有污点。
  • 解决
    1. 使用kubectl describe pod <pod-name>查看Events部分,通常会有明确的调度失败原因。
    2. 检查节点资源:kubectl describe node
    3. 检查节点污点:kubectl describe node | grep Taint

搭建Kubernetes集群是一个系统工程,涉及操作系统、网络、存储、安全等多个层面。这份指南覆盖了在CentOS 7上部署Kubernetes 1.20的核心路径和常见陷阱。实际操作中,你可能还会遇到硬盘空间不足、内核版本过低、特定硬件驱动等问题。我的建议是,保持耐心,善用kubectl describejournalctl -u kubelet等命令查看日志,大部分问题都能找到线索。把这个三节点的集群搭起来,只是Kubernetes之旅的第一步,后面还有存储、服务发现、负载均衡、监控日志等更广阔的天地等着你去探索。

http://www.zskr.cn/news/1535808.html

相关文章:

  • 网上流传的亨得利全是真的吗?2026亨得利官方权威实地核查曝光大量虚假渠道,手把手教大家规避维修消费陷阱 - 亨得利官方维修中心
  • 长沙熙林国际会议中心:一站式专业会议酒店服务标杆 - 奔跑123
  • 2026深圳龙岗包包回收测评 五家机构扣费透明度评级 - 逸程
  • 避坑指南:国产服务器做RAID时硬盘状态变‘Unconfigured Bad’怎么办?附蜂鸣警报关闭方法
  • 3分钟上手LunaTranslator:打破语言障碍,畅玩日系游戏的终极翻译方案
  • MidScene:用自然语言重新定义跨平台自动化测试
  • 深度解析EPPlus架构设计与企业级Excel自动化实战指南
  • 财税Agent选购避坑指南:不能同步财税新政的产品真的需要每年大额付费升级吗?
  • 如何用清华简约主题PPT模板告别学术汇报的设计烦恼
  • 3分钟上手Notepad--:国产跨平台编辑器的正确打开方式
  • 3个步骤轻松掌握ConfuserEx:保护你的.NET代码不被反编译
  • GitOps核心原理:声明式配置与Git作为唯一真相源
  • 终极指南:如何使用memtest_vulkan快速检测GPU显存稳定性与故障
  • 世界模型:DreamerV3、GAIA-1 在机器人预测中的应用
  • 3分钟掌握Translumo:Windows平台终极屏幕实时翻译神器
  • 在浏览器中实现专业级CAD建模:OpenCascade.js完全指南
  • Bandizip深度解析:从多核压缩到智能解压,打造高效文件管理方案
  • 10分钟打造专业短视频:揭秘AI视频创作神器MoneyPrinterTurbo
  • TV Bro电视浏览器:3分钟掌握大屏上网的终极遥控器优化方案
  • 2026重庆办公室装修与酒店装修设计公司评测:从公装实力到专业深度 - 深度智识库
  • 扩散策略:Diffusion Policy for Robotic Manipulation
  • Boss-Key:Windows平台终极隐私保护神器,一键隐藏窗口快速切换
  • 魔兽争霸3性能优化终极指南:5步解锁高帧率与宽屏体验
  • 2026 年五大美利奴羊毛户外服饰品牌实力梳理与解析 - 深度智识库
  • 晋中闲置黄金变现指南 多家实体回收门店对比与交易须知 - 润富黄金回收
  • Gradient Boosting实战:从梯度下降原理到AUC提升0.03的调参逻辑
  • 2026年AI编程助手选型指南:从Copilot替代到工程实体重构
  • 哈尔滨铜门生产厂家排行:基于工程案例与服务能力的客观盘点 - 奔跑123
  • 100万条医疗对话如何重塑中国医疗AI的未来?
  • 如何用ROFL-Player解决英雄联盟回放文件兼容性问题:终极免费方案