1. 项目概述与核心目标最近在帮团队搭建一套用于内部开发测试的Kubernetes环境选定的基础操作系统是CentOS 7.9Kubernetes版本则定位在相对稳定且兼容性经过验证的1.20系列。之所以选择这个组合一方面是考虑到公司内部仍有大量存量应用运行在CentOS 7上迁移成本较高另一方面K8s 1.20是一个承上启下的版本它已经包含了相当多稳定的特性同时又避开了早期版本的一些已知坑点对于学习和中小规模部署来说非常合适。这个安装过程看似是标准操作但在实际的机房或云主机环境中从系统初始化到集群就绪每一步都藏着细节网络配置、镜像拉取、组件版本匹配任何一个环节出问题都可能导致部署失败。接下来我就把这次从零开始在CentOS 7上成功部署K8s 1.20单控制平面集群的完整操作过程、踩过的坑以及总结的避坑指南毫无保留地分享出来。无论你是刚开始接触容器编排的运维新人还是需要快速搭建一套测试环境的老手这份详尽的记录都能让你少走弯路。2. 环境准备与系统初始化在开始安装Kubernetes任何组件之前我们必须为它准备一个“干净”且“合规”的操作系统环境。这里的“干净”指的是关闭可能干扰集群网络和服务的系统服务“合规”则是指系统参数、内核模块等需要满足K8s运行的最低要求。很多安装失败的问题根源都出在这一步。2.1 基础系统要求与规划首先你需要准备至少两台CentOS 7.9的虚拟机或物理机。一台作为控制平面节点Master另一台作为工作节点Worker。对于实验环境Master节点建议配置2核CPU、4GB内存、40GB磁盘Worker节点建议2核CPU、2GB内存、40GB磁盘。生产环境请根据实际负载大幅提高配置。所有节点需要确保网络互通且每个节点有唯一的主机名。防火墙和SELinux需要被正确配置或关闭这是初期避免网络问题最直接的方式。需要配置一个稳定的软件源用于安装Docker、Kubernetes组件等。我个人的习惯是在开始任何操作前先在所有节点上执行一遍系统更新和主机名设置。# 在所有节点上执行 # 1. 更新系统并安装基础工具 yum update -y yum install -y vim wget net-tools bash-completion # 2. 设置永久主机名以master节点为例 hostnamectl set-hostname k8s-master # 在worker节点上执行hostnamectl set-hostname k8s-worker1 # 3. 修改 /etc/hosts 文件添加所有节点的IP和主机名映射 # 假设 master IP 为 192.168.1.100, worker1 IP 为 192.168.1.101 cat /etc/hosts EOF 192.168.1.100 k8s-master 192.168.1.101 k8s-worker1 EOF注意/etc/hosts的配置至关重要尤其是在没有内部DNS解析的环境下。Kubernetes组件之间、节点之间需要通过主机名相互通信。务必确保每个节点上的这个文件内容一致且准确。2.2 关键系统服务与安全配置接下来是关闭防火墙和SELinux。在安全要求严格的生成环境你可能需要配置精细的防火墙规则和SELinux策略但对于学习和测试环境关闭它们可以极大简化问题排查的复杂度。# 在所有节点上执行 # 1. 关闭并禁用防火墙firewalld systemctl stop firewalld systemctl disable firewalld # 2. 关闭SELinux临时生效永久生效 setenforce 0 # 临时设置为宽松模式 sed -i s/^SELINUXenforcing$/SELINUXpermissive/ /etc/selinux/config # 永久修改为permissive为什么是permissive而不是disabled将SELinux设置为permissive模式意味着系统会记录违反策略的操作但不阻止它。这既能让我们顺利安装又能在日志中看到哪些操作可能被SELinux拦截为日后开启安全策略提供参考。直接disabled可能会在后续某些操作中遇到更隐晦的问题。2.3 内核参数与模块加载Kubernetes对Linux内核有一些要求特别是网络和存储方面。我们需要加载必要的内核模块并调整一些系统参数。# 在所有节点上执行 # 1. 加载内核模块 cat /etc/modules-load.d/k8s.conf EOF br_netfilter ip_vs ip_vs_rr ip_vs_sh ip_vs_wrr nf_conntrack EOF # 手动加载模块重启后也会自动加载 modprobe br_netfilter modprobe ip_vs modprobe ip_vs_rr modprobe ip_vs_sh modprobe ip_vs_wrr modprobe nf_conntrack # 2. 配置系统参数 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 vm.swappiness 0 EOF # 使配置生效 sysctl --system参数解析net.bridge.bridge-nf-call-iptables 1这是让iptables规则能够对桥接网络流量生效的关键参数。Kubernetes Service和网络策略NetworkPolicy都依赖于此。net.ipv4.ip_forward 1开启IP转发这是容器跨节点通信和Service网络模式如NodePort的基础。vm.swappiness 0尽可能避免使用交换分区Swap。Kubernetes从1.8版本开始就要求关闭Swap但有些环境无法彻底关闭设置为0可以最大程度减少Swap使用因为Swap会导致kubelet性能不可预测。2.4 配置国内Yum源与时间同步由于网络原因直接使用默认的国外源安装Docker和K8s可能会非常慢甚至失败。配置国内镜像源是必选项。同时集群所有节点的时间必须同步否则证书、日志等都会出问题。# 在所有节点上执行 # 1. 备份原有yum源 mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/ # 2. 下载阿里云CentOS 7镜像源这里以Base源为例EPEL源同样需要配置 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # 清理缓存并重建 yum clean all yum makecache # 3. 安装并配置NTP时间同步 yum install -y ntpdate # 使用阿里云的NTP服务器 ntpdate ntp1.aliyun.com # 设置定时任务每30分钟同步一次 echo */30 * * * * /usr/sbin/ntpdate ntp1.aliyun.com /dev/null 21 /etc/crontab systemctl restart crond做完以上所有步骤请务必重启所有节点。重启可以确保所有内核模块、系统参数和主机名更改完全生效。这是避免后续出现各种灵异问题的重要一步。3. 容器运行时与Kubernetes组件安装环境准备好后我们开始安装核心软件容器运行时和Kubernetes组件。这里我们选择Docker作为容器运行时并使用阿里云镜像站来加速Kubernetes组件的下载。3.1 安装与配置DockerKubernetes 1.20版本对Docker的支持是“最后的美好时光”从1.24版本开始K8s就移除了对Docker的直接支持。所以1.20版本是我们仍能使用Docker的稳定选择。我们安装指定版本的Docker-ce。# 在所有节点上执行 # 1. 安装yum工具包 yum install -y yum-utils device-mapper-persistent-data lvm2 # 2. 添加阿里云Docker CE镜像源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 3. 安装指定版本的Docker这里选择19.03.15与k8s 1.20兼容性好 yum install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io # 4. 配置Docker镜像加速和Cgroup驱动 mkdir -p /etc/docker 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://registry.docker-cn.com, https://hub-mirror.c.163.com, https://mirror.baidubce.com ] } EOF关键配置解析native.cgroupdriversystemd这是至关重要的一步。必须将Docker的Cgroup驱动设置为systemd使其与Kubernetes kubelet的默认驱动保持一致。如果不一致kubelet将无法正确管理Docker创建的容器导致节点状态异常。storage-driver: overlay2Overlay2是CentOS 7上推荐且性能较好的存储驱动。registry-mirrors配置国内镜像加速器可以极大提升拉取Docker官方镜像的速度。# 5. 启动并设置Docker开机自启 systemctl daemon-reload systemctl enable docker --now # 6. 验证Docker安装和配置 docker info | grep -i cgroup # 输出中应包含 Cgroup Driver: systemd3.2 安装Kubernetes组件kubeadm kubelet kubectl我们将使用kubeadm这个官方推荐的集群部署工具。同样为了速度我们配置阿里云的Kubernetes镜像源。# 在所有节点上执行 # 1. 添加阿里云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 # 2. 安装指定版本的kubelet kubeadm kubectl (1.20.15是一个稳定的补丁版本) yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15 --disableexcludeskubernetes # 3. 设置kubelet开机自启先不启动等kubeadm init后再启动 systemctl enable kubelet--disableexcludeskubernetes这个参数是为了防止在安装时因为某些仓库的排除规则而导致kubelet等包被跳过。3.3 配置kubelet的Cgroup驱动确保kubelet的Cgroup驱动与Docker保持一致。编辑kubelet的默认配置文件。# 在所有节点上执行 cat /etc/sysconfig/kubelet EOF KUBELET_EXTRA_ARGS--cgroup-driversystemd EOF至此所有节点上的软件都已安装完毕。接下来我们将在Master节点上初始化控制平面。4. 使用Kubeadm初始化Master节点kubeadm init是创建Kubernetes控制平面的核心命令。这个过程中会生成集群证书、部署核心组件如API Server Controller Manager Scheduler etcd并生成加入集群的令牌。4.1 初始化命令与参数详解在Master节点k8s-master上执行初始化。这里有几个关键参数需要根据你的环境调整。# 仅在Master节点执行 # 1. 预先拉取所需的镜像避免init时因网络问题超时 kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers # 2. 执行初始化命令 kubeadm init \ --apiserver-advertise-address192.168.1.100 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.20.15 \ --service-cidr10.96.0.0/12 \ --pod-network-cidr10.244.0.0/16 \ --ignore-preflight-errorsSwap参数拆解与避坑指南--apiserver-advertise-address指定API Server对外公告的IP地址。必须填写Master节点的实际IP不能是127.0.0.1。Worker节点将通过这个地址连接到Master。--image-repository指定拉取K8s核心组件镜像的仓库。使用阿里云镜像站registry.aliyuncs.com/google_containers速度比谷歌原厂仓库快几个数量级。--kubernetes-version必须与我们安装的kubeadm版本严格一致这里是v1.20.15。--service-cidrKubernetes Service的虚拟IP地址段。使用默认的10.96.0.0/12即可除非和你现有的网络冲突。--pod-network-cidr这是为后续安装Pod网络插件CNI准备的。这里设置为10.244.0.0/16是因为我们将使用flannel网络插件这是flannel默认的网段。如果你计划使用Calico、Weave Net等其他插件这个网段可能需要修改。--ignore-preflight-errorsSwap因为我们之前只将swappiness设为0并未彻底关闭Swap分区所以初始化时会有一个警告。这个参数用于忽略Swap检查的警告。如果Swap已彻底关闭swapoff -a并注释掉/etc/fstab中的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 Alternatively, if you are the root user, you can run: export KUBECONFIG/etc/kubernetes/admin.conf 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 abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx请务必立即执行以下操作配置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记录kubeadm join命令将最后输出的kubeadm join ...命令完整地保存下来。这个命令包含了令牌和CA证书哈希用于Worker节点加入集群。令牌默认24小时有效。可选启用Master节点调度Pod默认情况下出于安全考虑Master节点不允许调度普通的Pod。在测试环境中如果你只有一台Master节点可以解除这个限制。kubectl taint nodes --all node-role.kubernetes.io/master-4.3 安装Pod网络插件CNI没有网络插件集群内的Pod无法跨节点通信。我们选择最经典且简单的flannel。# 在Master节点执行 # 注意这里使用的镜像仓库是docker.io如果拉取慢可以尝试先手动拉取或配置Docker镜像加速器。 kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml应用这个YAML文件后Kubernetes会在kube-system命名空间下创建一系列DaemonSet等资源。使用以下命令查看安装状态kubectl get pods -n kube-system -l appflannel # 等待所有Pod状态变为 Running kubectl get nodes # 此时Master节点的状态应该从 NotReady 变为 Ready当Master节点状态显示为Ready说明控制平面和网络插件都已正常运行。现在Master节点已经就绪可以接受Worker节点加入了。5. Worker节点加入集群与集群验证现在我们将Worker节点加入到刚刚创建好的集群中。5.1 执行加入集群命令在每一台Worker节点上执行之前在Master节点初始化成功后输出的kubeadm join命令。命令格式如下请替换为你自己的令牌和哈希# 在Worker节点k8s-worker1上执行 kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx如果令牌过期可以在Master节点上重新生成# 在Master节点执行 kubeadm token create --print-join-command5.2 验证节点加入状态回到Master节点使用kubectl查看节点状态。kubectl get nodes你应该能看到类似下面的输出STATUS栏都显示为ReadyNAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 10m v1.20.15 k8s-worker1 Ready none 2m v1.20.155.3 部署测试应用验证集群功能集群状态就绪后我们部署一个最简单的Nginx应用来验证整个集群是否工作正常。部署一个Nginx Deploymentkubectl create deployment nginx-test --imagenginx:1.21-alpine将Nginx服务暴露为NodePort类型kubectl expose deployment nginx-test --port80 --typeNodePort查看服务详情kubectl get svc nginx-test输出中会有一个PORT(S)列例如80:30678/TCP。30678就是集群随机分配的NodePort。访问测试 打开浏览器访问http://任意节点的IP:30678。如果看到Nginx的欢迎页面恭喜你一个功能完整的Kubernetes集群已经部署成功查看Pod调度情况kubectl get pods -o wide这个命令可以看到Pod运行在哪个节点上以及它的IP地址这有助于理解K8s的调度和网络。6. 安装后的优化与常见问题排查集群跑起来只是第一步要让其稳定、好用还需要一些优化配置。同时我把安装过程中最容易遇到的几个问题及其解决方案记录下来。6.1 核心优化配置配置kubectl命令自动补全# bash用户 echo source (kubectl completion bash) ~/.bashrc source ~/.bashrc # zsh用户 echo source (kubectl completion zsh) ~/.zshrc source ~/.zshrc配置kube-proxy的IPVS模式可选但推荐kube-proxy默认使用iptables模式当Service数量非常多时超过几千iptables规则会变得庞大影响性能。可以改为ipvs模式效率更高。# 编辑kube-proxy的ConfigMap kubectl edit configmap kube-proxy -n kube-system在data.config.conf部分找到mode: 将其修改为mode: ipvs保存退出。然后删除现有的kube-proxy Pod让其重建。kubectl get pod -n kube-system -l k8s-appkube-proxy -o name | xargs kubectl delete -n kube-system等待新的Pod启动后验证模式kubectl logs -n kube-system kube-proxy-pod-name | grep -i Using ipvs配置Docker和kubelet日志轮转防止日志占满磁盘。Docker我们之前在daemon.json中配置的max-size参数已生效。Kubelet编辑/etc/systemd/system/kubelet.service.d/10-kubeadm.conf在[Service]部分添加EnvironmentKUBELET_CONFIG_ARGS--config/var/lib/kubelet/config.yaml --log-file/var/log/kubelet.log --logtostderrfalse --rotate-log-file --rotate-log-max-size100 --rotate-log-max-backups5然后执行systemctl daemon-reload systemctl restart kubelet。6.2 常见问题排查实录问题1kubeadm init时卡在[preflight]或拉取镜像失败。原因网络问题无法连接到镜像仓库。解决确保已配置国内镜像源阿里云。可以手动预拉取镜像kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers。检查节点是否能正常访问外网ping mirrors.aliyun.com。问题2Worker节点kubeadm join失败提示connection refused或证书错误。原因Master节点的6443端口API Server未开放或被防火墙拦截。节点间主机名解析失败。初始化时--apiserver-advertise-address填错。解决在Master节点检查端口netstat -tlnp | grep 6443。检查Master和Worker节点的/etc/hosts文件确保能互相解析主机名。检查Master节点防火墙和SELinux是否已按步骤关闭。问题3节点状态为NotReady。原因通常是网络插件flannel没有成功运行。解决kubectl get pods -n kube-system查看kube-flannel-ds-*Pod的状态。如果是ImagePullBackOff可能是网络问题拉取不到quay.io的镜像。可以尝试修改flannel的YAML文件将镜像地址替换为国内源如registry.cn-hangzhou.aliyuncs.com/google_containers/flannel但要注意版本匹配操作较复杂。更简单的方法是确保节点能访问外网或配置Docker代理。journalctl -u kubelet -f查看kubelet日志寻找具体错误信息。问题4Pod一直处于Pending状态。原因通常是资源不足CPU/内存或没有满足条件的节点如Master节点不可调度。解决kubectl describe pod pod-name查看事件Events里面会有详细的调度失败原因。如果是node(s) didn‘t have enough resource考虑增加节点资源或减少Pod请求资源。如果是node(s) had taint {node-role.kubernetes.io/master: }说明Pod被调度到了Master节点但被污点排斥。可以给Pod添加容忍度Toleration或者在测试环境下直接去除Master节点的污点如前文所述。问题5Service的NodePort无法访问。原因节点防火墙未开放NodePort端口范围默认是30000-32767。kube-proxy服务异常。解决在测试环境可以临时在节点上开放端口范围firewall-cmd --permanent --add-port30000-32767/tcp firewall-cmd --reload如果防火墙开启的话。检查kube-proxyPod是否运行正常kubectl get pods -n kube-system -l k8s-appkube-proxy。整个安装过程最考验耐心的是网络和环境问题。严格按照步骤操作并理解每一步的作用遇到问题时查看组件日志journalctl -u kubeletdocker logs container-idkubectl logs pod-name大部分都能找到线索。这个在CentOS 7上搭建的K8s 1.20集群已经可以作为你学习容器编排、部署测试应用甚至搭建CI/CD环境的坚实基础。
CentOS 7.9 上部署 Kubernetes 1.20 集群:从环境准备到应用验证的完整实践
发布时间:2026/6/16 16:48:52
1. 项目概述与核心目标最近在帮团队搭建一套用于内部开发测试的Kubernetes环境选定的基础操作系统是CentOS 7.9Kubernetes版本则定位在相对稳定且兼容性经过验证的1.20系列。之所以选择这个组合一方面是考虑到公司内部仍有大量存量应用运行在CentOS 7上迁移成本较高另一方面K8s 1.20是一个承上启下的版本它已经包含了相当多稳定的特性同时又避开了早期版本的一些已知坑点对于学习和中小规模部署来说非常合适。这个安装过程看似是标准操作但在实际的机房或云主机环境中从系统初始化到集群就绪每一步都藏着细节网络配置、镜像拉取、组件版本匹配任何一个环节出问题都可能导致部署失败。接下来我就把这次从零开始在CentOS 7上成功部署K8s 1.20单控制平面集群的完整操作过程、踩过的坑以及总结的避坑指南毫无保留地分享出来。无论你是刚开始接触容器编排的运维新人还是需要快速搭建一套测试环境的老手这份详尽的记录都能让你少走弯路。2. 环境准备与系统初始化在开始安装Kubernetes任何组件之前我们必须为它准备一个“干净”且“合规”的操作系统环境。这里的“干净”指的是关闭可能干扰集群网络和服务的系统服务“合规”则是指系统参数、内核模块等需要满足K8s运行的最低要求。很多安装失败的问题根源都出在这一步。2.1 基础系统要求与规划首先你需要准备至少两台CentOS 7.9的虚拟机或物理机。一台作为控制平面节点Master另一台作为工作节点Worker。对于实验环境Master节点建议配置2核CPU、4GB内存、40GB磁盘Worker节点建议2核CPU、2GB内存、40GB磁盘。生产环境请根据实际负载大幅提高配置。所有节点需要确保网络互通且每个节点有唯一的主机名。防火墙和SELinux需要被正确配置或关闭这是初期避免网络问题最直接的方式。需要配置一个稳定的软件源用于安装Docker、Kubernetes组件等。我个人的习惯是在开始任何操作前先在所有节点上执行一遍系统更新和主机名设置。# 在所有节点上执行 # 1. 更新系统并安装基础工具 yum update -y yum install -y vim wget net-tools bash-completion # 2. 设置永久主机名以master节点为例 hostnamectl set-hostname k8s-master # 在worker节点上执行hostnamectl set-hostname k8s-worker1 # 3. 修改 /etc/hosts 文件添加所有节点的IP和主机名映射 # 假设 master IP 为 192.168.1.100, worker1 IP 为 192.168.1.101 cat /etc/hosts EOF 192.168.1.100 k8s-master 192.168.1.101 k8s-worker1 EOF注意/etc/hosts的配置至关重要尤其是在没有内部DNS解析的环境下。Kubernetes组件之间、节点之间需要通过主机名相互通信。务必确保每个节点上的这个文件内容一致且准确。2.2 关键系统服务与安全配置接下来是关闭防火墙和SELinux。在安全要求严格的生成环境你可能需要配置精细的防火墙规则和SELinux策略但对于学习和测试环境关闭它们可以极大简化问题排查的复杂度。# 在所有节点上执行 # 1. 关闭并禁用防火墙firewalld systemctl stop firewalld systemctl disable firewalld # 2. 关闭SELinux临时生效永久生效 setenforce 0 # 临时设置为宽松模式 sed -i s/^SELINUXenforcing$/SELINUXpermissive/ /etc/selinux/config # 永久修改为permissive为什么是permissive而不是disabled将SELinux设置为permissive模式意味着系统会记录违反策略的操作但不阻止它。这既能让我们顺利安装又能在日志中看到哪些操作可能被SELinux拦截为日后开启安全策略提供参考。直接disabled可能会在后续某些操作中遇到更隐晦的问题。2.3 内核参数与模块加载Kubernetes对Linux内核有一些要求特别是网络和存储方面。我们需要加载必要的内核模块并调整一些系统参数。# 在所有节点上执行 # 1. 加载内核模块 cat /etc/modules-load.d/k8s.conf EOF br_netfilter ip_vs ip_vs_rr ip_vs_sh ip_vs_wrr nf_conntrack EOF # 手动加载模块重启后也会自动加载 modprobe br_netfilter modprobe ip_vs modprobe ip_vs_rr modprobe ip_vs_sh modprobe ip_vs_wrr modprobe nf_conntrack # 2. 配置系统参数 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 vm.swappiness 0 EOF # 使配置生效 sysctl --system参数解析net.bridge.bridge-nf-call-iptables 1这是让iptables规则能够对桥接网络流量生效的关键参数。Kubernetes Service和网络策略NetworkPolicy都依赖于此。net.ipv4.ip_forward 1开启IP转发这是容器跨节点通信和Service网络模式如NodePort的基础。vm.swappiness 0尽可能避免使用交换分区Swap。Kubernetes从1.8版本开始就要求关闭Swap但有些环境无法彻底关闭设置为0可以最大程度减少Swap使用因为Swap会导致kubelet性能不可预测。2.4 配置国内Yum源与时间同步由于网络原因直接使用默认的国外源安装Docker和K8s可能会非常慢甚至失败。配置国内镜像源是必选项。同时集群所有节点的时间必须同步否则证书、日志等都会出问题。# 在所有节点上执行 # 1. 备份原有yum源 mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/ # 2. 下载阿里云CentOS 7镜像源这里以Base源为例EPEL源同样需要配置 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo # 清理缓存并重建 yum clean all yum makecache # 3. 安装并配置NTP时间同步 yum install -y ntpdate # 使用阿里云的NTP服务器 ntpdate ntp1.aliyun.com # 设置定时任务每30分钟同步一次 echo */30 * * * * /usr/sbin/ntpdate ntp1.aliyun.com /dev/null 21 /etc/crontab systemctl restart crond做完以上所有步骤请务必重启所有节点。重启可以确保所有内核模块、系统参数和主机名更改完全生效。这是避免后续出现各种灵异问题的重要一步。3. 容器运行时与Kubernetes组件安装环境准备好后我们开始安装核心软件容器运行时和Kubernetes组件。这里我们选择Docker作为容器运行时并使用阿里云镜像站来加速Kubernetes组件的下载。3.1 安装与配置DockerKubernetes 1.20版本对Docker的支持是“最后的美好时光”从1.24版本开始K8s就移除了对Docker的直接支持。所以1.20版本是我们仍能使用Docker的稳定选择。我们安装指定版本的Docker-ce。# 在所有节点上执行 # 1. 安装yum工具包 yum install -y yum-utils device-mapper-persistent-data lvm2 # 2. 添加阿里云Docker CE镜像源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo # 3. 安装指定版本的Docker这里选择19.03.15与k8s 1.20兼容性好 yum install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io # 4. 配置Docker镜像加速和Cgroup驱动 mkdir -p /etc/docker 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://registry.docker-cn.com, https://hub-mirror.c.163.com, https://mirror.baidubce.com ] } EOF关键配置解析native.cgroupdriversystemd这是至关重要的一步。必须将Docker的Cgroup驱动设置为systemd使其与Kubernetes kubelet的默认驱动保持一致。如果不一致kubelet将无法正确管理Docker创建的容器导致节点状态异常。storage-driver: overlay2Overlay2是CentOS 7上推荐且性能较好的存储驱动。registry-mirrors配置国内镜像加速器可以极大提升拉取Docker官方镜像的速度。# 5. 启动并设置Docker开机自启 systemctl daemon-reload systemctl enable docker --now # 6. 验证Docker安装和配置 docker info | grep -i cgroup # 输出中应包含 Cgroup Driver: systemd3.2 安装Kubernetes组件kubeadm kubelet kubectl我们将使用kubeadm这个官方推荐的集群部署工具。同样为了速度我们配置阿里云的Kubernetes镜像源。# 在所有节点上执行 # 1. 添加阿里云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 # 2. 安装指定版本的kubelet kubeadm kubectl (1.20.15是一个稳定的补丁版本) yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15 --disableexcludeskubernetes # 3. 设置kubelet开机自启先不启动等kubeadm init后再启动 systemctl enable kubelet--disableexcludeskubernetes这个参数是为了防止在安装时因为某些仓库的排除规则而导致kubelet等包被跳过。3.3 配置kubelet的Cgroup驱动确保kubelet的Cgroup驱动与Docker保持一致。编辑kubelet的默认配置文件。# 在所有节点上执行 cat /etc/sysconfig/kubelet EOF KUBELET_EXTRA_ARGS--cgroup-driversystemd EOF至此所有节点上的软件都已安装完毕。接下来我们将在Master节点上初始化控制平面。4. 使用Kubeadm初始化Master节点kubeadm init是创建Kubernetes控制平面的核心命令。这个过程中会生成集群证书、部署核心组件如API Server Controller Manager Scheduler etcd并生成加入集群的令牌。4.1 初始化命令与参数详解在Master节点k8s-master上执行初始化。这里有几个关键参数需要根据你的环境调整。# 仅在Master节点执行 # 1. 预先拉取所需的镜像避免init时因网络问题超时 kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers # 2. 执行初始化命令 kubeadm init \ --apiserver-advertise-address192.168.1.100 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.20.15 \ --service-cidr10.96.0.0/12 \ --pod-network-cidr10.244.0.0/16 \ --ignore-preflight-errorsSwap参数拆解与避坑指南--apiserver-advertise-address指定API Server对外公告的IP地址。必须填写Master节点的实际IP不能是127.0.0.1。Worker节点将通过这个地址连接到Master。--image-repository指定拉取K8s核心组件镜像的仓库。使用阿里云镜像站registry.aliyuncs.com/google_containers速度比谷歌原厂仓库快几个数量级。--kubernetes-version必须与我们安装的kubeadm版本严格一致这里是v1.20.15。--service-cidrKubernetes Service的虚拟IP地址段。使用默认的10.96.0.0/12即可除非和你现有的网络冲突。--pod-network-cidr这是为后续安装Pod网络插件CNI准备的。这里设置为10.244.0.0/16是因为我们将使用flannel网络插件这是flannel默认的网段。如果你计划使用Calico、Weave Net等其他插件这个网段可能需要修改。--ignore-preflight-errorsSwap因为我们之前只将swappiness设为0并未彻底关闭Swap分区所以初始化时会有一个警告。这个参数用于忽略Swap检查的警告。如果Swap已彻底关闭swapoff -a并注释掉/etc/fstab中的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 Alternatively, if you are the root user, you can run: export KUBECONFIG/etc/kubernetes/admin.conf 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 abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx请务必立即执行以下操作配置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记录kubeadm join命令将最后输出的kubeadm join ...命令完整地保存下来。这个命令包含了令牌和CA证书哈希用于Worker节点加入集群。令牌默认24小时有效。可选启用Master节点调度Pod默认情况下出于安全考虑Master节点不允许调度普通的Pod。在测试环境中如果你只有一台Master节点可以解除这个限制。kubectl taint nodes --all node-role.kubernetes.io/master-4.3 安装Pod网络插件CNI没有网络插件集群内的Pod无法跨节点通信。我们选择最经典且简单的flannel。# 在Master节点执行 # 注意这里使用的镜像仓库是docker.io如果拉取慢可以尝试先手动拉取或配置Docker镜像加速器。 kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml应用这个YAML文件后Kubernetes会在kube-system命名空间下创建一系列DaemonSet等资源。使用以下命令查看安装状态kubectl get pods -n kube-system -l appflannel # 等待所有Pod状态变为 Running kubectl get nodes # 此时Master节点的状态应该从 NotReady 变为 Ready当Master节点状态显示为Ready说明控制平面和网络插件都已正常运行。现在Master节点已经就绪可以接受Worker节点加入了。5. Worker节点加入集群与集群验证现在我们将Worker节点加入到刚刚创建好的集群中。5.1 执行加入集群命令在每一台Worker节点上执行之前在Master节点初始化成功后输出的kubeadm join命令。命令格式如下请替换为你自己的令牌和哈希# 在Worker节点k8s-worker1上执行 kubeadm join 192.168.1.100:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx如果令牌过期可以在Master节点上重新生成# 在Master节点执行 kubeadm token create --print-join-command5.2 验证节点加入状态回到Master节点使用kubectl查看节点状态。kubectl get nodes你应该能看到类似下面的输出STATUS栏都显示为ReadyNAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 10m v1.20.15 k8s-worker1 Ready none 2m v1.20.155.3 部署测试应用验证集群功能集群状态就绪后我们部署一个最简单的Nginx应用来验证整个集群是否工作正常。部署一个Nginx Deploymentkubectl create deployment nginx-test --imagenginx:1.21-alpine将Nginx服务暴露为NodePort类型kubectl expose deployment nginx-test --port80 --typeNodePort查看服务详情kubectl get svc nginx-test输出中会有一个PORT(S)列例如80:30678/TCP。30678就是集群随机分配的NodePort。访问测试 打开浏览器访问http://任意节点的IP:30678。如果看到Nginx的欢迎页面恭喜你一个功能完整的Kubernetes集群已经部署成功查看Pod调度情况kubectl get pods -o wide这个命令可以看到Pod运行在哪个节点上以及它的IP地址这有助于理解K8s的调度和网络。6. 安装后的优化与常见问题排查集群跑起来只是第一步要让其稳定、好用还需要一些优化配置。同时我把安装过程中最容易遇到的几个问题及其解决方案记录下来。6.1 核心优化配置配置kubectl命令自动补全# bash用户 echo source (kubectl completion bash) ~/.bashrc source ~/.bashrc # zsh用户 echo source (kubectl completion zsh) ~/.zshrc source ~/.zshrc配置kube-proxy的IPVS模式可选但推荐kube-proxy默认使用iptables模式当Service数量非常多时超过几千iptables规则会变得庞大影响性能。可以改为ipvs模式效率更高。# 编辑kube-proxy的ConfigMap kubectl edit configmap kube-proxy -n kube-system在data.config.conf部分找到mode: 将其修改为mode: ipvs保存退出。然后删除现有的kube-proxy Pod让其重建。kubectl get pod -n kube-system -l k8s-appkube-proxy -o name | xargs kubectl delete -n kube-system等待新的Pod启动后验证模式kubectl logs -n kube-system kube-proxy-pod-name | grep -i Using ipvs配置Docker和kubelet日志轮转防止日志占满磁盘。Docker我们之前在daemon.json中配置的max-size参数已生效。Kubelet编辑/etc/systemd/system/kubelet.service.d/10-kubeadm.conf在[Service]部分添加EnvironmentKUBELET_CONFIG_ARGS--config/var/lib/kubelet/config.yaml --log-file/var/log/kubelet.log --logtostderrfalse --rotate-log-file --rotate-log-max-size100 --rotate-log-max-backups5然后执行systemctl daemon-reload systemctl restart kubelet。6.2 常见问题排查实录问题1kubeadm init时卡在[preflight]或拉取镜像失败。原因网络问题无法连接到镜像仓库。解决确保已配置国内镜像源阿里云。可以手动预拉取镜像kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers。检查节点是否能正常访问外网ping mirrors.aliyun.com。问题2Worker节点kubeadm join失败提示connection refused或证书错误。原因Master节点的6443端口API Server未开放或被防火墙拦截。节点间主机名解析失败。初始化时--apiserver-advertise-address填错。解决在Master节点检查端口netstat -tlnp | grep 6443。检查Master和Worker节点的/etc/hosts文件确保能互相解析主机名。检查Master节点防火墙和SELinux是否已按步骤关闭。问题3节点状态为NotReady。原因通常是网络插件flannel没有成功运行。解决kubectl get pods -n kube-system查看kube-flannel-ds-*Pod的状态。如果是ImagePullBackOff可能是网络问题拉取不到quay.io的镜像。可以尝试修改flannel的YAML文件将镜像地址替换为国内源如registry.cn-hangzhou.aliyuncs.com/google_containers/flannel但要注意版本匹配操作较复杂。更简单的方法是确保节点能访问外网或配置Docker代理。journalctl -u kubelet -f查看kubelet日志寻找具体错误信息。问题4Pod一直处于Pending状态。原因通常是资源不足CPU/内存或没有满足条件的节点如Master节点不可调度。解决kubectl describe pod pod-name查看事件Events里面会有详细的调度失败原因。如果是node(s) didn‘t have enough resource考虑增加节点资源或减少Pod请求资源。如果是node(s) had taint {node-role.kubernetes.io/master: }说明Pod被调度到了Master节点但被污点排斥。可以给Pod添加容忍度Toleration或者在测试环境下直接去除Master节点的污点如前文所述。问题5Service的NodePort无法访问。原因节点防火墙未开放NodePort端口范围默认是30000-32767。kube-proxy服务异常。解决在测试环境可以临时在节点上开放端口范围firewall-cmd --permanent --add-port30000-32767/tcp firewall-cmd --reload如果防火墙开启的话。检查kube-proxyPod是否运行正常kubectl get pods -n kube-system -l k8s-appkube-proxy。整个安装过程最考验耐心的是网络和环境问题。严格按照步骤操作并理解每一步的作用遇到问题时查看组件日志journalctl -u kubeletdocker logs container-idkubectl logs pod-name大部分都能找到线索。这个在CentOS 7上搭建的K8s 1.20集群已经可以作为你学习容器编排、部署测试应用甚至搭建CI/CD环境的坚实基础。