ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

CentOS 8上部署Kubernetes 1.18集群:从零搭建与生产级实践指南

CentOS 8上部署Kubernetes 1.18集群:从零搭建与生产级实践指南 1. 项目缘起与核心价值最近在整理一些遗留项目的技术栈发现不少老系统还跑在CentOS 8上而容器编排的需求又迫在眉睫。直接升级操作系统或者迁移到新平台成本太高于是就有了在CentOS 8上原地部署一套Kubernetes 1.18集群的需求。这个版本组合听起来有点“复古”但恰恰是很多企业从传统虚拟化向容器化平稳过渡的真实场景。Kubernetes 1.18是一个承上启下的LTS版本它修复了之前版本的一些关键问题同时API又相对稳定不会像更高版本那样引入大量变动对于生产环境来说稳定压倒一切。而CentOS 8尽管其官方支持已经结束但在国内仍有大量存量服务器其稳定的RPM包管理和对传统硬件的良好兼容性使得它依然是许多运维团队熟悉的“战场”。这次部署的核心价值不仅仅是把k8s跑起来更在于构建一个在“老旧但稳定”的基础设施上依然能提供现代化容器编排能力的可靠平台。它解决的是资源受限、升级窗口短、求稳不求新的典型企业痛点。无论你是运维工程师需要维护历史资产还是开发者想在一个可控的环境里深入学习Kubernetes的底层机制这个从零开始搭建1.18版本集群的过程都能给你带来从系统配置、网络规划到组件调优的全链路实战经验。整个过程会涉及操作系统基础配置、容器运行时选型、核心组件部署以及网络插件集成我会把每一步背后的“为什么”都讲清楚并附上我趟过的坑和验证有效的技巧。2. CentOS 8基础环境准备与关键配置在开始安装Kubernetes任何组件之前我们必须为它准备一个“干净且强壮”的宿主系统。很多部署失败的问题根源都出在这一步。2.1 系统初始化与关键参数调优首先确保你的CentOS 8是最小化安装这能减少不必要的软件包冲突。更新系统并安装基础工具是第一步dnf update -y dnf install -y vim wget curl net-tools telnet yum-utils device-mapper-persistent-data lvm2接下来是几个必须调整的内核参数它们直接关系到Kubernetes的稳定运行。编辑/etc/sysctl.d/k8s.conf文件net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 vm.swappiness 0net.bridge.bridge-nf-call-iptables 1: 这是为了让iptables规则能够对桥接的流量生效这是Calico、Flannel等网络插件正常工作所必需的。没有它你的Pod很可能无法跨节点通信。net.ipv4.ip_forward 1: 启用IP转发这是网络路由的基础。Pod网络通常是一个独立的网段数据包需要经过宿主机的转发才能到达其他节点或外网。vm.swappiness 0: 尽可能避免使用交换分区。Kubernetes对内存敏感使用交换分区会导致性能急剧下降和不可预测的行为尤其是在kubelet管理Pod生命周期时。加载配置sysctl --system。这里有个坑如果你在虚拟机环境下运行并且发现sysctl报错说net.bridge参数不存在那是因为br_netfilter内核模块没有加载。手动加载它modprobe br_netfilter并确保开机自动加载echo br_netfilter /etc/modules-load.d/k8s.conf。2.2 容器运行时安装为何选择Docker而非ContainerdKubernetes 1.18版本官方对Docker的支持还处于鼎盛时期。虽然现在更推荐Containerd但在CentOS 8这个特定环境下选择Docker 19.03.x有它的道理。首先CentOS 8默认的软件源里Docker的安装和依赖解决更顺畅。其次Docker的工具链如docker ps,docker logs对于还处于过渡期的团队来说调试更直观。当然我们需要安装的是旧版Docker CE。# 添加Docker官方仓库注意CentOS 8的软件源架构可能已变这里使用可靠的旧仓库 dnf config-manager --add-repohttps://download.docker.com/linux/centos/docker-ce.repo # 安装指定版本避免最新版可能的不兼容 dnf install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io安装后必须配置Docker的Cgroup驱动为systemd这与kubelet保持一致否则kubelet会无法启动。编辑/etc/docker/daemon.json如果不存在就创建{ exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m }, storage-driver: overlay2, storage-opts: [ overlay2.override_kernel_checktrue ] }启动并设置开机自启systemctl enable --now docker。验证驱动docker info | grep Cgroup应显示Cgroup Driver: systemd。2.3 关闭并禁用不必要服务防火墙与SELinux的取舍这是一个经典的抉择。对于学习或测试环境我建议直接关闭防火墙和SELinux能避免大量诡异问题。systemctl stop firewalld systemctl disable firewalld setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config注意在生产环境中直接关闭防火墙是危险的。更安全的做法是配置firewalld规则放行Kubernetes所需端口如6443, 2379-2380, 10250, 10251, 10252, 30000-32767等。但鉴于我们是在一个相对隔离的环境搭建关闭它以简化问题是更务实的选择。SELinux在容器场景下配置复杂关闭它也是常见的实践。2.4 配置Kubernetes阿里云镜像源由于网络原因直接使用谷歌的仓库几乎不可能成功。使用阿里云的镜像源是必须的。为yum添加Kubernetes仓库cat EOF /etc/yum.repos.d/kubernetes.repo [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关键点注意这里使用的是el7的仓库而不是el8。这是因为Kubernetes官方对CentOS 8/RHEL 8的软件包支持在早期版本并不完善使用el7的包在CentOS 8上兼容性更好这是经过大量实践验证的。3. Kubernetes 1.18 核心组件安装与Master节点初始化基础环境就绪后我们开始安装Kubernetes的核心三件套kubeadm, kubelet, kubectl。3.1 安装指定版本组件并锁定我们明确安装1.18.20这个版本它是一个较晚的1.18补丁版本相对更稳定。dnf install -y kubelet-1.18.20 kubeadm-1.18.20 kubectl-1.18.20 --disableexcludeskubernetes--disableexcludeskubernetes这个参数很重要它告诉yum在安装或更新时不要排除kubernetes相关的包防止后续操作因包排除而失败。安装完成后启动kubelet并设置开机自启systemctl enable --now kubelet。但此时kubelet会不断重启报错这是正常的因为它还在等待kubeadm的初始化指令。3.2 使用kubeadm init初始化Master节点这是最核心的一步。我们需要创建一个初始化配置文件而不是直接使用命令行参数这样更清晰且易于版本控制。创建kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration kubernetesVersion: v1.18.20 controlPlaneEndpoint: k8s-master:6443 # 使用主机名需确保/etc/hosts解析或DNS可用 imageRepository: registry.aliyuncs.com/google_containers # 使用阿里云镜像仓库 networking: podSubnet: 10.244.0.0/16 # 为后续安装Flannel网络插件预留Flannel默认使用此网段 serviceSubnet: 10.96.0.0/12 apiServer: certSANs: # 证书扩展域名很重要 - k8s-master - 192.168.1.100 # 你的Master节点IP地址 - 127.0.0.1controlPlaneEndpoint: 这里我使用了主机名k8s-master。你必须确保所有节点包括Master自己都能通过这个主机名解析到Master节点的IP地址。最稳妥的方法是在每个节点的/etc/hosts文件中添加记录192.168.1.100 k8s-master。imageRepository: 这是成功的关键。将镜像源指向阿里云可以极大提升拉取镜像的速度和成功率。podSubnet: 我们计划使用Flannel作为网络插件vxlan模式它的默认网段就是10.244.0.0/16这里预先配置好。certSANs: 务必把你访问API Server可能用到的所有地址主机名、IP、回环地址都加进去否则后续用kubectl或Dashboard连接时可能会遇到证书错误。执行初始化命令kubeadm init --configkubeadm-config.yaml --upload-certs--upload-certs参数会将生成的证书加密上传便于后续其他控制平面节点加入如果你要做高可用集群的话。这个过程会持续几分钟它会从阿里云拉取所有必要的镜像如kube-apiserver, kube-controller-manager, etcd等并生成一系列证书和静态Pod清单。初始化成功后的关键操作 初始化完成后命令行会输出几行非常重要的信息务必复制保存你的kubeconfig文件配置命令它通常长这样mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config执行它这样你才能以普通用户身份使用kubectl。Node节点加入集群的命令以kubeadm join开头包含令牌和哈希值。这个命令有时效性默认24小时如果过期可以用kubeadm token create --print-join-command重新生成。3.3 安装Pod网络插件CNIFlannel在Master节点初始化后CoreDNS等系统Pod会处于Pending状态因为它们需要网络插件才能被调度。我们安装最经典的Flannel。# 下载Flannel的配置文件注意我们指定了与kubeadm配置一致的pod网段 wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml # 应用这个配置文件 kubectl apply -f kube-flannel.yml应用后使用kubectl get pods -n kube-system -w观察kube-flannelPod的状态直到全部变为Running。此时再检查CoreDNS Podkubectl get pods -n kube-system应该也会很快变成Running。为什么选择Flannel在1.18这个版本Flannel的简单、稳定和广泛的社区支持是最大的优势。它的vxlan后端性能不错且配置简单几乎不需要额外调整就能工作。对于刚入门的集群它是风险最低的选择。4. Worker节点加入集群与基础功能验证Master节点准备就绪后就可以将其他CentOS 8服务器作为Worker节点加入集群。4.1 Worker节点环境准备在每一台要加入的Worker节点上重复第2章的所有步骤系统更新与工具安装。内核参数调整与模块加载。安装相同版本的Docker19.03.15并进行相同配置。关闭防火墙和SELinux或按生产环境配置规则。配置阿里云Kubernetes仓库并安装相同版本的kubelet和kubeadm不需要kubectl。4.2 执行加入命令在Worker节点上运行之前在Master节点初始化成功后得到的kubeadm join命令。命令格式类似kubeadm join k8s-master:6443 --token your-token \ --discovery-token-ca-cert-hash sha256:your-hash如果令牌已过期回到Master节点执行kubeadm token create --print-join-command生成新的命令。加入成功后在Master节点上执行kubectl get nodes稍等片刻你应该能看到新加入的节点状态从NotReady变为Ready。NotReady状态通常是因为Flannel的Pod还没有在该节点上完全启动等待一两分钟即可。4.3 基础集群功能验证节点就绪后我们需要运行一些测试来确保集群核心功能正常。测试1部署一个测试应用kubectl create deployment nginx-test --imagenginx:1.18-alpine kubectl expose deployment nginx-test --port80 --typeNodePort这条命令创建了一个Nginx Deployment并通过NodePort服务暴露出来。执行kubectl get svc nginx-test你会看到类似80:3xxxx/TCP的输出其中3xxxx是一个随机的高位端口30000-32767。测试2检查Pod调度与网络kubectl get pods -o wide查看Nginx Pod被调度到了哪个节点比如Worker节点。然后从集群内任意节点包括Master或集群外访问该Worker节点的IP地址和上面得到的NodePort端口例如http://worker-ip:3xxxx。如果能看到Nginx欢迎页说明Pod调度、网络Flannel、服务发现和负载均衡kube-proxy全部工作正常。测试3检查DNS解析kubectl run busybox --imagebusybox:1.28 --restartNever --rm -it -- sh # 进入busybox容器后执行 nslookup kubernetes.default如果能够成功解析出kubernetes.default.svc.cluster.local的集群IP通常是10.96.0.1说明CoreDNS工作正常这是服务发现的基础。5. 生产环境考量与常见故障排查一个能跑起来的集群只是一个开始要用于生产或严肃测试还需要考虑更多。5.1 关键组件的健康检查与日志学会查看核心组件的日志是运维的基本功。所有Master组件apiserver, scheduler, controller-manager都以静态Pod形式运行在kube-system命名空间。查看所有系统Pod状态kubectl get pods -n kube-system -o wide查看特定组件日志例如kube-apiserver# 先找到apiserver的Pod名字 kubectl get pods -n kube-system -l componentkube-apiserver # 查看日志 kubectl logs -n kube-system apiserver-pod-name查看kubelet日志在节点上journalctl -u kubelet -f5.2 镜像拉取策略与私有仓库在企业内部我们不可能每次都从公网拉取镜像。你需要配置Docker使用私有镜像仓库。在每台节点上登录私有仓库docker login myprivateregistry.com。对于Kubernetes需要在Pod定义中指定imagePullSecrets。首先创建一个docker-registry类型的Secretkubectl create secret docker-registry regcred \ --docker-servermyprivateregistry.com \ --docker-usernameyour-name \ --docker-passwordyour-password \ --docker-emailyour-email在Deployment的Pod模板中引用这个Secretspec: containers: - name: myapp image: myprivateregistry.com/myapp:v1 imagePullSecrets: - name: regcred5.3 存储与持久化卷的早期规划即使是测试集群如果涉及有状态应用也需要考虑存储。在1.18版本你可以从最简单的hostPath卷开始测试但生产环境需要更可靠的方案如NFS、Ceph RBD或云厂商的块存储。你需要提前安装对应的CSI容器存储接口驱动。例如对于NFS可以部署nfs-subdir-external-provisioner它能动态创建PV。5.4 高频故障点与排查思路节点状态一直NotReady检查kubectl describe node node-name查看Conditions部分。常见原因网络插件未就绪kubectl get pods -n kube-system -o wide | grep flannel看对应节点的Flannel Pod是否Running。kubelet未运行在节点上执行systemctl status kubelet。防火墙/安全组阻断了节点间通信特别是8472端口Flannel VXLAN和10250端口kubelet API。Pod一直处于Pending状态检查kubectl describe pod pod-name。常见原因资源不足CPU/内存。没有满足NodeSelector或Affinity的节点。持久化卷声明PVC无法绑定。Pod处于ImagePullBackOff或ErrImagePull状态检查kubectl describe pod pod-name查看Events部分。常见原因镜像名称拼写错误。私有镜像仓库未配置imagePullSecrets或认证失败。网络问题导致镜像拉取超时。kubectl命令执行卡住或无响应检查Master节点的kube-apiserverPod是否正常运行。检查Master节点的网络连接。检查$HOME/.kube/config文件中的server地址是否正确证书是否有效。6. 集群维护与后续升级路径部署完成只是第一步日常维护和未来的升级路径更需要规划。6.1 基础备份etcd数据Kubernetes的所有状态除了Pod里运行的应用数据都存储在etcd中。定期备份etcd是灾难恢复的底线。# 在Master节点上执行 ETCDCTL_API3 etcdctl --endpointshttps://127.0.0.1:2379 \ --cacert/etc/kubernetes/pki/etcd/ca.crt \ --cert/etc/kubernetes/pki/etcd/server.crt \ --key/etc/kubernetes/pki/etcd/server.key \ snapshot save /opt/etcd-snapshot-$(date %Y%m%d).db将生成的.db文件转移到安全的异地位置。恢复时使用etcdctl snapshot restore命令。6.2 资源监控与告警入门一个没有监控的集群就像在黑夜中开车。你可以从最简单的方案开始部署metrics-server。它是Kubernetes核心指标管道为kubectl top和HPA自动水平扩缩容提供资源使用数据。# 下载较新版本的metrics-server配置兼容1.18 wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml # 修改components.yaml中的args添加两个关键参数以跳过TLS验证仅限测试环境 # 在 metrics-server Deployment 的 args 部分添加 # - --kubelet-insecure-tls # - --kubelet-preferred-address-typesInternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP kubectl apply -f components.yaml部署后等待Pod运行然后就可以使用kubectl top nodes和kubectl top pods查看资源使用情况了。6.3 关于升级的严肃建议你现在拥有的是一个Kubernetes 1.18集群。官方对1.18的支持早已结束。这意味着没有安全补丁和bug修复。这个集群绝对不应该用于暴露在公网或有真实业务数据的生产环境。它的定位应该是内部开发测试、学习Kubernetes原理、为遗留应用提供临时容器化环境的跳板。如果你的目标是将生产环境迁移到Kubernetes正确的路径是用这个1.18集群作为技术和人员的“练兵场”。规划全新的、基于当前受支持Kubernetes版本如1.27和现代操作系统如Rocky Linux 9, Ubuntu 22.04 LTS的生产集群。将应用逐步从旧集群迁移到新集群。kubeadm集群的升级路径非常狭窄且风险高尤其是跨多个大版本升级几乎等同于重建。在整个部署和验证过程中我最大的体会是文档上的命令往往只是理想路径实际环境总会给你“惊喜”。比如内核模块缺失、镜像拉取超时、证书SAN配置不全等。解决问题的关键不是死记命令而是学会使用kubectl describe、kubectl logs和journalctl这些工具去看日志、看事件、看状态描述它们提供的错误信息能直接指引你找到问题的根源。另外好记性不如烂笔头像kubeadm join命令、镜像仓库地址、关键配置文件的内容一定要及时保存下来。这个在CentOS 8上搭建K8s 1.18的过程更像是一次对Kubernetes基础架构的深度解剖理解了这些再去看更高级的版本或发行版你会觉得轻松很多。
返回列表