CentOS 7 实战部署 Kubernetes 1.20 集群:从系统配置到网络插件详解

📅 2026/6/16 13:51:59
CentOS 7 实战部署 Kubernetes 1.20 集群:从系统配置到网络插件详解
1. 项目概述与核心价值如果你正在使用 CentOS 7 系统并且需要部署一个稳定、可用于生产或学习环境的 Kubernetes 1.20 集群那么这篇手把手的实战指南就是为你准备的。Kubernetes 1.20 是一个承上启下的重要版本它引入了不少新特性同时也移除了一些旧的、废弃的 API对于希望从更老版本升级或者新搭建集群的团队来说是一个非常好的起点。然而在 CentOS 7 这个相对“经典”的系统上安装 K8s 1.20你可能会遇到一些特有的“坑”比如系统内核参数、防火墙规则、软件包依赖以及国内网络环境下的镜像拉取问题。我花了几天时间在三台 CentOS 7.9 的虚拟机上完整复现了整个安装过程从系统初始化到集群网络打通把每一步的操作、背后的原理以及可能遇到的报错和解决方案都记录了下来。这篇文章的目标是让你能“开箱即用”直接复制命令就能搭建起一个可用的集群同时也能理解每个步骤的意义这样在遇到环境差异时你也能自己排查和解决。无论你是运维工程师、开发人员还是正在学习云原生的学生这份详尽的记录都能帮你绕过我踩过的那些坑高效地完成集群部署。2. 环境准备与前置条件解析在开始敲命令之前充分的准备工作是成功的一半。Kubernetes 对运行环境有一些明确的要求如果不满足kubeadm init命令会在预检阶段就直接报错退出。这一节我们来详细拆解这些前置条件并解释为什么需要这么做。2.1 硬件与系统要求首先你需要至少两台机器虚拟机或物理机。一台作为控制平面节点Master另一台作为工作节点Worker。对于学习和测试一台 Master 和一台 Worker 是最小配置生产环境建议至少三个 Master 以实现高可用。我本次演示的环境如下Master 节点: k8s-master, IP: 192.168.110.10Worker 节点 1: k8s-node1, IP: 192.168.110.11Worker 节点 2: k8s-node2, IP: 192.168.110.12所有机器均安装CentOS 7.9 Minimal版本。系统要求如下CPU: 至少 2 核。Master 节点运行多个控制平面组件资源消耗更大。内存: 至少 2GB。建议 Master 节点 2GBWorker 节点根据实际负载决定学习环境 1GB 也可运行。磁盘: 至少 20GB。需要存放系统、Docker 镜像和容器日志。网络: 所有节点间网络互通并且 Master 节点的 6443 端口API Server需要对其他节点开放。注意务必确保三台机器的时间同步。Kubernetes 对证书和日志的时间戳非常敏感。可以使用chronyd或ntp服务进行同步。一个快速的检查命令是date看看各节点时间是否基本一致。2.2 关键系统配置与内核参数调优这是 CentOS 7 下安装 K8s 最容易出问题的地方。我们需要对系统进行一系列配置以满足容器运行时的要求。1. 关闭 SELinux 和 SwapSELinux 在强制模式下可能会干扰容器对主机资源的访问导致各种权限问题。对于学习或内部测试环境最简单的做法是将其设置为permissive或直接disabled。生产环境如需开启则需要配置复杂的策略这超出了入门指南的范围。# 临时设置为宽松模式 setenforce 0 # 永久禁用修改配置文件 sed -i s/^SELINUXenforcing$/SELINUXdisabled/ /etc/selinux/configSwap 交换分区必须关闭。Kubernetes 设计之初就假设节点资源是确定性的Swap 的引入会导致资源调度变得不可预测可能引发 Pod 被错误地驱逐。kubeadm会严格检查此项。# 临时关闭所有 Swap 分区 swapoff -a # 永久关闭注释掉 /etc/fstab 中所有 swap 相关的行 sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab2. 配置防火墙规则CentOS 7 默认使用firewalld。我们需要放行 Kubernetes 组件通信所需的端口而不是简单粗暴地关闭防火墙。以下是关键端口Master 节点: 6443 (API Server), 2379-2380 (etcd), 10250 (kubelet API), 10251 (scheduler), 10252 (controller manager)Worker 节点: 10250 (kubelet API), 30000-32767 (NodePort 服务范围)为了方便我们可以设置默认区域为trusted信任所有连接或者在public区域添加规则。这里采用设置信任区域的方式firewall-cmd --set-default-zonetrusted --permanent firewall-cmd --reload实操心得如果你在公有云上操作除了系统防火墙还需要在云服务商的安全组规则中放行上述端口否则节点间依然无法通信。3. 配置网络转发与桥接流量容器网络依赖于 Linux 内核的网桥和路由功能。必须启用 IP 转发并让iptables能够看到桥接的流量。# 加载 br_netfilter 模块 modprobe br_netfilter # 创建配置文件 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 --systemnet.bridge.bridge-nf-call-iptables1这一条至关重要。它确保经过网桥的流量也会经过iptables的过滤规则这是 Calico、Flannel 等 CNI 插件正常工作如网络策略的基础。4. 配置 Docker 的 Cgroup 驱动Kubernetes 推荐使用systemd作为 Cgroup 驱动而 Docker 默认使用cgroupfs。两者不一致会导致kubelet启动失败。我们需要统一为systemd。# 创建或修改 Docker 的 daemon.json 配置文件 cat /etc/docker/daemon.json EOF { exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m }, storage-driver: overlay2, registry-mirrors: [https://你的镜像加速器地址.mirror.aliyuncs.com] } EOF配置中的registry-mirrors请替换为你的阿里云镜像加速器地址需要注册阿里云账号获取这能极大提升拉取 Docker 镜像的速度。配置完成后重启 Docker 服务systemctl restart docker。2.3 主机名与 hosts 文件配置清晰的节点标识有助于管理和排查问题。为每个节点设置唯一的主机名并在所有节点的/etc/hosts文件中添加 IP 与主机名的映射。# 在 Master 节点上 hostnamectl set-hostname k8s-master # 在 Node1 节点上 hostnamectl set-hostname k8s-node1 # 在 Node2 节点上 hostnamectl set-hostname k8s-node2 # 编辑所有节点的 /etc/hosts 文件添加如下内容 192.168.110.10 k8s-master 192.168.110.11 k8s-node1 192.168.110.12 k8s-node2配置完成后互相ping一下主机名确保能解析到正确的 IP 并通信。3. 核心组件安装与配置详解环境准备妥当后我们就可以开始安装 Kubernetes 的核心组件了容器运行时Docker和 Kubernetes 三件套kubeadm, kubelet, kubectl。3.1 Docker 安装与关键配置虽然 Kubernetes 支持多种容器运行时CRI-O, containerd 等但 Docker 依然是生态最完善、资料最丰富的选择。我们安装指定版本20.10.x以保持兼容性。# 1. 安装 yum 工具包并设置稳定的仓库 yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 2. 安装指定版本的 Docker CE yum install -y docker-ce-20.10.23 docker-ce-cli-20.10.23 containerd.io # 3. 启动并设置开机自启 systemctl enable docker --now安装完成后验证 Docker 版本和 Cgroup 驱动docker --version docker info | grep Cgroup确认输出中的Cgroup Driver是systemd。如果不是请检查上一步的/etc/docker/daemon.json配置是否正确并重启 Docker。3.2 Kubernetes 仓库配置与组件安装Kubernetes 官方仓库地址在国内访问可能不稳定我们可以使用阿里云提供的镜像仓库。# 创建 Kubernetes 的 yum 仓库文件 cat /etc/yum.repos.d/kubernetes.repo EOF [kubernetes] nameKubernetes baseurlhttps://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ enabled1 gpgcheck1 repo_gpgcheck1 gpgkeyhttps://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF接下来安装指定版本的 kubelet, kubeadm 和 kubectl。这里有个大坑默认情况下yum 可能会排除 Kubernetes 仓库中的包我们需要使用--disableexcludeskubernetes参数来确保安装成功。# 安装 1.20.15 版本一个稳定的 1.20 小版本 yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15 --disableexcludeskubernetes # 启动 kubelet 并设置开机自启 systemctl enable kubelet --now此时运行systemctl status kubelet你会发现它处于不断重启crashloop的状态这是正常的。因为kubelet会持续尝试连接 API Server但此时集群尚未初始化API Server 不存在所以会失败。等我们初始化集群后它就会自动恢复正常。4. 使用 Kubeadm 初始化 Master 节点kubeadm是 Kubernetes 官方推荐的集群引导工具它极大地简化了安装流程。初始化 Master 节点是构建集群最关键的一步。4.1 预拉取镜像与初始化命令解析在运行kubeadm init之前可以先拉取所需的镜像避免初始化过程因网络超时而失败。我们可以让kubeadm先拉取镜像kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.20.15这个命令会从阿里云镜像仓库拉取 8 个核心镜像包括kube-apiserver,kube-controller-manager,kube-scheduler,kube-proxy,pause,etcd以及两个coredns镜像。常见问题你可能会遇到coredns镜像拉取失败提示pull access denied。这是因为镜像名称在某个版本后发生了变化。如果遇到可以手动拉取并重命名docker pull coredns/coredns:1.7.0 docker tag coredns/coredns:1.7.0 registry.aliyuncs.com/google_containers/coredns:1.7.0 docker rmi coredns/coredns:1.7.0镜像准备就绪后执行初始化命令kubeadm init \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.20.15 \ --pod-network-cidr10.244.0.0/16 \ --apiserver-advertise-address192.168.110.10 \ --ignore-preflight-errorsSwap我们来拆解一下这几个参数--image-repository: 指定镜像仓库使用国内源加速。--kubernetes-version: 必须与安装的kubelet版本严格一致。--pod-network-cidr: 设置 Pod 网络的 CIDR。这里设置为10.244.0.0/16是为了后续安装 Flannel 网络插件其默认网段。如果你选择 Calico这个值通常设为192.168.0.0/16但也可以在 Calico 的配置文件中修改。--apiserver-advertise-address: 指定 API Server 对外公告的 IP 地址。如果你的 Master 节点有多个网卡务必指定内网 IP。--ignore-preflight-errorsSwap: 如果你确认已经关闭了 Swap但预检仍然报错可以用此参数忽略。但强烈建议还是从根本上解决 Swap 问题。4.2 初始化成功后的关键操作如果一切顺利命令执行完成后你会看到如下成功信息并包含两条非常重要的指令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.10:6443 --token token \ --discovery-token-ca-cert-hash sha256:hash第一条指令将集群的管理配置文件 (admin.conf) 复制到当前用户目录下并设置权限。这样你才能使用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查看节点状态此时 Master 节点应处于NotReady状态因为网络插件尚未安装。第二条指令kubeadm join ...这是 Worker 节点加入集群的命令。请务必保存好这个命令的输出或者记下其中的 token 和 hash。如果丢失可以在 Master 节点上重新生成# 生成新的 token kubeadm token create --print-join-command5. 部署 Pod 网络插件 (CNI)没有网络插件集群内的 Pod 无法跨节点通信节点状态永远是NotReady。CNI (Container Network Interface) 插件负责实现 Kubernetes 的网络模型。这里我以最常用的Flannel和功能更强大的Calico为例分别说明。5.1 方案一部署 Flannel简单稳定Flannel 是 CoreOS 团队维护的项目配置简单足够稳定是入门和测试环境的绝佳选择。它使用10.244.0.0/16作为 Pod 网段这也是为什么我们在kubeadm init时指定了相同的 CIDR。部署 Flannel 只需要一条命令kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml这个 YAML 文件会创建一个DaemonSet在每个节点上运行一个flanneldPod并配置必要的 RBAC 权限和网络资源。部署完成后等待片刻再次运行kubectl get nodes和kubectl get pods -n kube-system应该能看到 Master 节点状态变为Ready并且kube-flannel-*的 Pod 都在运行。注意事项Flannel 默认的后端是VXLAN性能有一定损耗。如果节点间网络性能要求高且在同一二层网络内可以考虑使用host-gw后端但配置稍复杂。另外Flannel 不支持网络策略NetworkPolicy如果你需要实现 Pod 间的网络隔离请选择 Calico。5.2 方案二部署 Calico功能全面Calico 提供了更丰富的功能包括高性能的网络方案支持 BGP 路由反射和强大的网络策略能力。如果你的环境对网络性能和安全有更高要求Calico 是更好的选择。首先下载 Calico 的部署清单文件。对于 Kubernetes 1.20建议使用 Calico v3.20 左右的版本。curl https://docs.projectcalico.org/manifests/calico.yaml -O关键修改你需要修改calico.yaml文件确保其 IP 池配置与kubeadm init时设置的--pod-network-cidr一致。使用grep -n “CALICO_IPV4POOL_CIDR” calico.yaml找到配置行通常在ConfigMap里将其值修改为10.244.0.0/16如果你初始化时用的是这个。或者如果你初始化时用了 Calico 常用的192.168.0.0/16这里就不需要改。修改完成后部署 Calicokubectl apply -f calico.yamlCalico 的部署会创建更多的自定义资源定义CRD因此启动会比 Flannel 慢一些。使用kubectl get pods -n calico-system --watch可以观察 Pod 的启动过程。当所有 Pod 都进入Running状态后节点状态就会变为Ready。5.3 网络插件故障排查如果部署网络插件后节点状态长时间未就绪可以按以下步骤排查检查 Pod 状态kubectl describe pod flannel/calico-pod-name -n kube-system查看事件和状态详情。检查日志kubectl logs flannel/calico-pod-name -n kube-system查看具体错误日志。检查内核模块确保ip_tables,iptable_filter,iptable_nat,br_netfilter等模块已加载 (lsmod | grep 模块名)。检查网络配置确认net.bridge.bridge-nf-call-iptables1已生效。Calico 特定问题如果节点主机有多块网卡Calico 可能选错了用于 Pod 通信的网卡。可以通过在calico.yaml的DaemonSet部分设置IP_AUTODETECTION_METHOD环境变量来指定网卡例如interfaceeth.*。6. Worker 节点加入集群与验证Master 节点就绪后就可以让 Worker 节点加入了。6.1 执行 Join 命令在每一台 Worker 节点上执行之前kubeadm init输出中保存的kubeadm join命令。你需要以 root 用户执行kubeadm join 192.168.110.10:6443 --token 你的token \ --discovery-token-ca-cert-hash sha256:你的hash如果 token 过期默认24小时在 Master 节点上使用kubeadm token create --print-join-command生成新的命令。加入过程中Worker 节点会从 Master 拉取必要的镜像如kube-proxy,pause并启动kubelet服务。加入成功后你会在 Master 节点上通过kubectl get nodes看到新加入的节点状态可能先是NotReady待网络插件 Pod 在该节点上启动完成后会变为Ready。6.2 集群功能验证所有节点都Ready后我们需要验证集群的基本功能是否正常。1. 查看集群状态kubectl get nodes -o wide kubectl get pods -n kube-system -o wide确保所有系统 Podcoredns, kube-proxy, flannel/calico都处于Running状态并且分布在不同的节点上。2. 部署一个测试应用创建一个简单的 Nginx Deployment 和 Service测试 Pod 调度、网络和 Service 发现。# test-nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx ports: - protocol: TCP port: 80 targetPort: 80 type: NodePort应用这个配置kubectl apply -f test-nginx.yaml。3. 验证测试应用# 查看 Pod 是否被调度到不同节点并运行 kubectl get pods -o wide -l appnginx # 查看 Service获取 NodePort 端口例如 30080 kubectl get svc nginx-service # 从集群内任一节点访问该 Service 的 ClusterIP curl ClusterIP # 从集群外通过任一节点的 IP 和 NodePort 访问 curl Node-IP:NodePort如果以上步骤都能成功返回 Nginx 的欢迎页面恭喜你一个功能完整的 Kubernetes 1.20 集群已经在 CentOS 7 上成功运行起来了7. 进阶配置与日常维护技巧集群搭建完成只是第一步要让其稳定运行并服务于业务还需要一些进阶配置和维护知识。7.1 配置 kubectl 自动补全和别名kubectl命令很长配置自动补全能极大提升效率。# Bash 用户 echo source (kubectl completion bash) ~/.bashrc echo alias kkubectl ~/.bashrc echo complete -F __start_kubectl k ~/.bashrc source ~/.bashrc # 安装 bash-completion 包如果未安装 yum install -y bash-completion之后你就可以用k get po来代替kubectl get pods了。7.2 管理 kubeadm 的证书kubeadm生成的证书默认有效期为一年。一年后集群 API 将无法访问。你需要定期更新或续订证书。# 检查证书有效期 kubeadm certs check-expiration # 更新所有证书在 Master 节点执行 kubeadm certs renew all # 更新后需要重启控制平面的静态 Pod (API Server, Controller Manager, Scheduler) # 最简单的方法是移动它们的 manifest 文件kubelet 会自动重建它们 mv /etc/kubernetes/manifests/kube-apiserver.yaml /tmp/ sleep 10 # 等待 kubelet 重建 Pod mv /tmp/kube-apiserver.yaml /etc/kubernetes/manifests/ # 对 kube-controller-manager.yaml 和 kube-scheduler.yaml 重复此操作更安全的方式是使用kubeadm alpha certs renew1.20版本或查阅官方文档进行证书管理。7.3 重置与清理节点如果安装过程中出现无法解决的问题或者需要将节点踢出集群可以使用kubeadm reset命令。# 在需要重置的节点上执行 kubeadm reset -f # 清理 iptables 规则和 CNI 配置 iptables -F iptables -t nat -F iptables -t mangle -F iptables -X rm -rf /etc/cni/net.d # 清理 kubelet 配置 rm -rf $HOME/.kube在 Master 节点上你还需要手动删除一些文件rm -rf /etc/kubernetes/和rm -rf ~/.kube/。注意此操作会摧毁集群请谨慎执行。7.4 监控与日志收集一个健康的集群需要可观测性。对于入门你可以先部署metrics-server来获取基础的资源监控数据CPU/内存这是kubectl top命令和 HPA 的基础。# 下载 metrics-server 的部署文件可能需要根据版本调整 kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 通常需要修改部署参数添加 --kubelet-insecure-tls 以跳过证书验证仅限测试环境 kubectl edit deploy metrics-server -n kube-system # 在 spec.template.spec.containers[0].args 中添加 # - --kubelet-insecure-tls部署成功后等待几分钟就可以使用kubectl top nodes和kubectl top pods查看资源使用情况了。8. 常见问题与故障排查实录在这一部分我汇总了在 CentOS 7 上部署 K8s 1.20 时最常遇到的几个“坑”及其解决方案。希望你能绕过它们。问题一kubeadm init 时卡在[preflight]或[kubelet-start]阶段可能原因 1: 节点间主机名解析失败或网络不通。排查:ping对方 IP 和主机名。检查/etc/hosts和防火墙规则。可能原因 2: 未关闭 Swap。排查: 执行free -h查看 Swap 行是否都为 0。确保已执行swapoff -a并修改了/etc/fstab。可能原因 3:br_netfilter模块未加载或sysctl配置未生效。排查:lsmod | grep br_netfilter。执行sysctl -p /etc/sysctl.d/k8s.conf并检查输出。问题二节点状态为NotReady可能原因 1: CNI 网络插件未安装或安装失败。排查:kubectl get pods -n kube-system查看flannel或calico相关 Pod 是否运行正常。查看其日志kubectl logs -n kube-system pod-name。可能原因 2:kubelet服务异常。排查: 在问题节点上执行systemctl status kubelet -l查看详细日志。常见错误是cgroup driver不一致检查 Docker 和 kubelet 的 Cgroup 驱动是否都是systemd(docker info | grep Cgroup和cat /var/lib/kubelet/config.yaml | grep cgroupDriver)。问题三Pod 一直处于Pending状态可能原因 1: 资源不足CPU/内存。排查:kubectl describe pod pod-name查看事件通常会有提示。kubectl get nodes看节点资源分配情况。可能原因 2: 没有合适的节点满足 Pod 的亲和性/反亲和性、污点容忍等调度要求。排查:kubectl describe pod pod-name查看事件。检查节点的污点kubectl describe node node-name | grep Taint和 Pod 的容忍度。问题四Service 的 NodePort 无法访问可能原因 1: 节点防火墙未放行 NodePort 范围30000-32767。排查: 在节点上执行firewall-cmd --list-ports或iptables -L -n -t nat | grep NodePort。在firewalld中添加规则firewall-cmd --add-port30000-32767/tcp --permanent firewall-cmd --reload。可能原因 2:kube-proxy未正常运行。排查:kubectl get pods -n kube-system -l k8s-appkube-proxy。查看其日志。问题五镜像拉取失败 (ImagePullBackOff)可能原因: Docker 镜像仓库访问超时或权限不足。排查:kubectl describe pod pod-name查看事件。如果是私有仓库需要创建imagePullSecrets。对于gcr.io等国外仓库可以通过配置 Docker 镜像加速器或提前将镜像导入到私有仓库解决。搭建 Kubernetes 集群是一个系统工程总会遇到各种小问题。我的经验是善用kubectl describe和kubectl logs命令它们能提供 80% 以上的故障线索。另外保持耐心一步步对照日志和文档排查问题最终都能解决。这个在 CentOS 7 上从零搭建 K8s 1.20 集群的过程虽然步骤繁多但每一步都有其明确的目的。当你成功看到所有节点Ready测试应用正常运行的那一刻会觉得这一切都是值得的。这份指南希望能成为你探索 Kubernetes 世界的一块坚实垫脚石。