从零搭建K8s容器云平台:虚拟机环境规划与集群部署全流程详解

📅 2026/8/27 2:27:51
从零搭建K8s容器云平台:虚拟机环境规划与集群部署全流程详解
1. 项目概述与核心价值最近在准备一个云计算技能大赛的容器云平台搭建项目我发现很多朋友无论是学生备赛还是刚入行的运维工程师都对如何从零开始、在虚拟机里搭建一个符合大赛标准的容器云平台感到头疼。这不仅仅是装个Docker那么简单它涉及到虚拟化环境准备、网络规划、容器编排平台部署、服务治理等一系列环节任何一个步骤卡壳都可能让整个项目停滞不前。我自己在多次备赛和实际项目部署中也踩过不少坑比如虚拟机网络不通、镜像拉取超时、集群节点无法加入等等。今天我就以一个“过来人”的身份把从虚拟机环境准备到最终部署一个稳定可用的容器云平台以Kubernetes为例的全过程以及背后的原理和避坑技巧系统地梳理一遍。无论你是为了参加技能大赛还是想搭建一个自己的实验环境来深入学习云计算和容器技术这篇内容都能给你提供一条清晰、可复现的路径。这个项目的核心在于理解“平台”而不仅仅是“工具”。我们不只是安装软件更是构建一个能够承载微服务应用、具备弹性伸缩和服务发现能力的云原生底座。整个过程会涵盖虚拟化软件选型、Linux系统配置、容器运行时安装、Kubernetes集群部署、以及必要的网络插件和存储方案。我会重点解释每个步骤“为什么”要这么做并提供实测有效的配置参数和命令确保你不仅能跟着做出来更能明白其中的道理。2. 环境规划与虚拟化平台搭建2.1 虚拟化软件选型与考量搭建容器云平台的第一步是为其准备一个隔离、可控且性能可调的“土壤”——虚拟机环境。市面上主流的虚拟化工具有VMware Workstation、VirtualBox以及KVM。对于技能大赛或学习环境我强烈推荐使用VMware Workstation Pro。原因有几个首先它的网络配置功能非常强大且直观可以轻松创建仅主机、NAT、桥接等多种网络模式这对于后续组建Kubernetes集群网络至关重要。其次它对主流Linux发行版的兼容性和性能优化做得比较好特别是磁盘和网络I/O方面。最后它的快照功能堪称“后悔药”在复杂的部署过程中你可以在关键步骤前创建快照一旦操作失误可以瞬间回滚极大提升了实验效率。注意确保你的物理机BIOS/UEFI设置中已开启CPU的虚拟化支持如Intel VT-x或AMD-V。这是所有虚拟化软件运行的基础否则在创建64位虚拟机或启动时可能会报错。2.2 虚拟机规格设计与资源分配资源分配不是越多越好而是要合理。一个典型的用于部署Kubernetes集群的虚拟机规划如下控制平面节点 (Master): 至少1台。这是集群的大脑负责调度和管理。建议分配2核CPU 4GB内存 40GB磁盘。内存不能太低否则kube-apiserver、etcd等核心组件可能运行不稳定。工作节点 (Worker): 至少2台。这是运行实际容器负载的节点。建议每台分配2核CPU 4GB内存 50GB磁盘。如果资源紧张1台Worker也可以但就无法体验Pod在多节点间调度的高可用特性了。网络方面我建议为所有虚拟机创建一个自定义的VMnet网络例如VMnet2并设置为“仅主机模式”。这样做的好处是所有虚拟机在一个与物理主机隔离的私有网络中它们之间可以互通并且可以通过主机的NAT上网但外部网络无法直接访问它们既安全又方便管理。为每台虚拟机设置固定的IP地址如192.168.100.10, 192.168.100.11, 192.168.100.12这将为后续Kubernetes集群的稳定组建打下坚实基础。2.3 操作系统安装与基础优化操作系统选择CentOS 7.9或Ubuntu 20.04/22.04 LTS。两者在社区支持和稳定性上都不错CentOS的文档可能更传统一些而Ubuntu的包管理器更便捷。这里以CentOS 7.9为例。安装时选择“最小化安装”即可减少不必要的软件包。安装完成后有几项必须做的基础优化关闭防火墙与SELinux在实验环境为了排除网络干扰我们通常临时关闭它们。生产环境则需按安全策略另行配置。# 关闭防火墙 systemctl stop firewalld systemctl disable firewalld # 关闭SELinux需重启生效 setenforce 0 sed -i s/^SELINUXenforcing/SELINUXdisabled/ /etc/selinux/config配置静态IP编辑/etc/sysconfig/network-scripts/ifcfg-ens33网卡名可能不同确保BOOTPROTOstatic并设置IPADDR、NETMASK、GATEWAY、DNS1。配置主机名与hosts解析为每台机器设置唯一主机名如k8s-master, k8s-node1并在所有节点的/etc/hosts文件中添加所有节点的IP和主机名映射。这是Kubernetes节点间通信识别的关键。# 在每台机器上执行假设IP和主机名如下 echo 192.168.100.10 k8s-master /etc/hosts echo 192.168.100.11 k8s-node1 /etc/hosts echo 192.168.100.12 k8s-node2 /etc/hosts配置时间同步集群内所有节点时间必须同步否则会导致证书错误、日志混乱等问题。yum install -y ntpdate ntpdate time.windows.com3. 容器运行时与Kubernetes组件部署3.1 容器运行时安装与配置Kubernetes需要一个容器运行时来拉取镜像和运行容器。虽然Docker是最广为人知的但从Kubernetes 1.24版本开始已移除内置的Docker支持dockershim。因此我们选择安装containerd它是CNCF毕业项目性能更好也是当前Kubernetes社区推荐的标准运行时。安装containerd可以通过yum直接安装或者从官方GitHub下载rpm包。安装后需要生成默认配置文件并启动服务。# 安装containerd yum install -y containerd.io # 生成默认配置 containerd config default /etc/containerd/config.toml # 修改配置将SystemdCgroup改为true以更好地与systemd集成 sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml # 启动并设置开机自启 systemctl daemon-reload systemctl enable --now containerd配置完成后可以使用ctr images pull nginx:alpine测试一下是否能正常拉取镜像。3.2 Kubernetes仓库配置与组件安装接下来我们需要在所有节点上安装Kubernetes的核心组件kubeadm集群初始化工具、kubelet节点代理、kubectl集群管理命令行工具。首先配置阿里云的Kubernetes Yum仓库这样下载速度会快很多。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然后安装指定版本的组件大赛通常有版本要求例如1.23.x。# 安装指定版本避免版本不兼容问题 yum install -y kubelet-1.23.10 kubeadm-1.23.10 kubectl-1.23.10 # 设置kubelet开机自启但先不启动等kubeadm init后再启动 systemctl enable kubelet实操心得务必在所有节点上安装完全相同版本的kubeadm、kubelet和kubectl。版本不一致是导致集群初始化失败或节点加入失败的常见原因。使用yum list installed | grep kube可以检查已安装的版本。3.3 系统内核参数与交换分区调整Linux内核有一些默认参数不适合运行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 0执行sysctl --system使配置生效。第一、二条是为了让网桥流量经过iptables这是Calico等网络插件工作的基础。第三条开启IP转发这是容器网络路由的必要条件。第四条将swappiness设置为0表示尽可能不使用交换分区因为swap会严重影响kubelet和容器运行的性能。此外必须禁用交换分区。Kubernetes从1.8开始要求关闭swap否则kubelet将无法启动。# 临时关闭 swapoff -a # 永久关闭注释掉/etc/fstab中swap相关的行 sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab4. 使用Kubeadm初始化与组建集群4.1 Master节点初始化准备工作完成后我们首先在规划为Master的节点上执行初始化。这里有一个关键点由于网络原因直接拉取Kubernetes核心镜像如kube-apiserver, kube-controller-manager等可能会失败。我们可以使用阿里云的镜像仓库预先拉取。# 查看kubeadm需要哪些镜像 kubeadm config images list --image-repository registry.aliyuncs.com/google_containers # 预先拉取这些镜像 kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers拉取成功后开始初始化集群。以下命令是一个示例你需要根据你的网络规划调整--apiserver-advertise-address和--pod-network-cidr。kubeadm init \ --apiserver-advertise-address192.168.100.10 \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.23.10 \ --service-cidr10.96.0.0/12 \ --pod-network-cidr192.168.0.0/16 \ --ignore-preflight-errorsSwap--apiserver-advertise-address: 指定Master节点的IP其他节点将通过这个地址访问API Server。--pod-network-cidr: 指定Pod网络的IP段必须与你将要安装的网络插件如Calico、Flannel的默认网段匹配否则网络插件无法工作。这里设为192.168.0.0/16是为了匹配后续安装的Calico默认配置。--ignore-preflight-errorsSwap: 如果你确认swap已关闭但仍报警告可以加此参数忽略。初始化成功后控制台会输出几行非常重要的信息一是kubeadm join命令及token用于Worker节点加入集群二是提示你配置kubectl的步骤。4.2 配置kubectl与管理集群按照初始化成功后的提示在Master节点上执行以下命令来配置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查看节点状态此时Master节点应处于NotReady状态因为还没有安装网络插件。4.3 Worker节点加入集群将初始化成功时输出的kubeadm join命令在每一台Worker节点上以root身份执行。命令大概长这样kubeadm join 192.168.100.10:6443 --token your-token \ --discovery-token-ca-cert-hash sha256:your-hash如果忘记token或hash可以在Master节点上使用kubeadm token create --print-join-command重新生成完整的加入命令。在所有Worker节点成功加入后回到Master节点再次执行kubectl get nodes你应该能看到所有节点但状态依然是NotReady。5. 容器网络与核心插件部署5.1 容器网络插件CNI选型与部署Pod之间要能通信必须安装容器网络接口CNI插件。Calico和Flannel是最流行的两个选择。Calico功能更强大支持网络策略NetworkPolicy性能也较好适合对网络有更高要求的场景。Flannel配置简单“开箱即用”。这里我们选择部署Calico。在Master节点上使用kubectl apply命令部署Calico的Manifest文件。务必确保你下载的Calico版本与你的Kubernetes版本兼容例如K8s v1.23对应Calico v3.23。# 下载Calico的部署清单 curl https://docs.projectcalico.org/manifests/calico.yaml -O # 部署Calico kubectl apply -f calico.yaml部署完成后使用kubectl get pods -n kube-system查看Calico相关的Pod名字前缀为calico-node和calico-kube-controllers等待它们全部变为Running状态。稍等片刻再运行kubectl get nodes所有节点的状态应该会变为Ready。这标志着你的Kubernetes集群最核心的部分已经就绪。5.2 服务发现与CoreDNS验证Kubernetes集群内置了一个DNS服务——CoreDNS它为集群内的Service和Pod提供域名解析。Calico部署后CoreDNS Pod应该会自动启动。你可以检查一下kubectl get pods -n kube-system -l k8s-appkube-dns为了测试集群内网络和DNS是否正常工作可以运行一个临时的BusyBox Pod来进行测试。kubectl run busybox --imagebusybox:1.28 --restartNever -- sleep 3600 # 等待Pod变成Running状态后执行命令测试DNS kubectl exec busybox -- nslookup kubernetes.default如果能够成功解析出kubernetes.default服务的集群IP通常是10.96.0.1说明集群内部的DNS服务工作正常。6. 平台功能验证与基础应用部署6.1 部署一个示例应用集群搭建好了我们来实际运行一个应用看看。部署一个最简单的Nginx Deployment并暴露为Service。# 创建一个名为nginx的Deployment使用nginx:alpine镜像启动2个副本 kubectl create deployment nginx --imagenginx:alpine --replicas2 # 将名为nginx的Deployment暴露为一个NodePort类型的Service kubectl expose deployment nginx --port80 --typeNodePort执行上述命令后你可以查看资源状态kubectl get deployments kubectl get pods -o wide # 查看Pod被调度到了哪个节点 kubectl get services nginx # 查看Service信息会显示一个30000的NodePort端口现在你可以通过任意节点的IP地址加上分配的NodePort端口例如http://192.168.100.11:3xxxx在浏览器中访问应该能看到Nginx的欢迎页面。这证明了你的集群能够成功调度Pod、提供服务发现和负载均衡。6.2 Dashboard可视化界面部署可选对于技能大赛或日常管理一个可视化界面非常有用。Kubernetes Dashboard是一个官方项目。但请注意它的部署和访问涉及权限配置相对复杂。下载Dashboard的推荐清单文件并部署。kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml创建管理员服务账户和集群角色绑定。需要创建一个名为dashboard-adminuser.yaml的文件内容参考官方文档。获取访问令牌Token。kubectl -n kubernetes-dashboard create token admin-user通过kubectl proxy在本地访问Dashboard。请注意Dashboard默认只允许本地访问且需要有效的Bearer Token。生产环境务必配置更安全的访问方式如Ingress TLS。7. 常见故障排查与性能调优要点7.1 集群初始化与节点加入失败这是新手最容易遇到问题的地方。请务必按顺序检查以下环节镜像拉取失败这是最常见的问题。症状是kubeadm init卡在Pull images阶段。一定要使用--image-repository参数指定国内镜像源并提前执行kubeadm config images pull。端口占用6443API Server、10250kubelet等端口被占用。使用netstat -tlnp | grep 端口号检查并关闭冲突进程。网络不通Master与Worker节点之间网络不通。使用ping命令检查互通性并确认防火墙和SELinux已关闭/etc/hosts解析正确。Token过期kubeadm join的token默认24小时有效。过期后需要在Master节点用kubeadm token create重新创建。证书问题如果初始化中途失败重试可能遗留了旧的证书文件。可以执行kubeadm reset清理环境然后重新初始化。7.2 Pod状态异常与网络问题如果Pod一直处于Pending、ContainerCreating或Error状态可以按以下思路排查kubectl describe pod pod-name查看Pod的详细事件这是最直接的排错手段。常见原因有镜像拉取失败ImagePullBackOff、节点资源不足Insufficient cpu/memory、调度失败例如有节点选择器或污点。kubectl logs pod-name查看Pod内容器的日志输出。网络问题如果Pod是Running状态但无法跨节点通信首先检查Calico/Flannel的Pod是否运行正常。然后可以检查节点路由表ip route看是否有到其他节点Pod网段的路由。对于Calico还需要检查calico-node容器日志。7.3 性能与稳定性调优建议对于技能大赛环境除了能跑起来稳定和高效也很重要。资源预留在/var/lib/kubelet/config.yaml中可以配置systemReserved和kubeReserved为系统和Kubernetes组件预留一定的CPU和内存防止系统关键进程因资源竞争被OOM Killer杀死。日志与存储默认容器日志会一直增长需要配置日志轮转。编辑/etc/docker/daemon.json如果使用Docker或containerd的配置设置max-size和max-file。考虑部署一个日志收集系统如EFK和监控系统如PrometheusGrafana这是大赛的加分项。镜像加速在节点上配置国内镜像仓库加速器如阿里云、中科大镜像可以极大加快Pod的启动速度。这需要在容器运行时containerd或Docker的配置文件中配置registry-mirrors。整个搭建过程就像搭积木每一步都依赖前一步的稳固。我的经验是严格按照文档操作理解每个命令的作用遇到错误不要慌善用describe、logs、journalctl -u kubelet等命令查看日志大部分问题都能找到线索。最后别忘了利用好虚拟机的快照功能在完成每个关键阶段如系统初始化、组件安装、集群初始化后创建一个快照这能为你节省大量排错时间。