本文记录使用 kubeadm 在 Ubuntu 24.04 上部署一套三节点 Kubernetes 1.30.2 集群的完整过程。每个命令都标注了在哪台机器上执行读者照着敲即可。1. 环境说明1.1 软件版本组件版本宿主机VMware Workstation 17操作系统Ubuntu 24.04 Server (minimal)Kubernetes1.30.2containerd1.7.20nerdctl1.7.7CNI plugins1.6.01.2 虚拟机配置2 vCPU / 4 GB 内存 / 100 GB 硬盘一张 NAT 网卡不创建 swap 分区Kubernetes 强制要求1.3 节点规划主机名IP角色master30.k8s.local10.1.8.30control-planeworker31.k8s.local10.1.8.31workerworker32.k8s.local10.1.8.32worker阅读提示每个命令块黑底彩字的第一行就是执行该命令的机器比如[rootmaster30 ~]#表示在 master30 上以 root 身份执行。命令的输出结果放在灰色引用块中一眼就能区分。2. 安装方式选择Kubernetes 有多种安装方式各有利弊方式适用场景推荐度kubeadm生产自建、CKA 考试、标准集群⭐⭐⭐⭐⭐二进制手工原理研究、深度定制⭐⭐Sealos / KubeKey快速搭建⭐⭐⭐⭐k3s / k0s边缘节点、低配机器⭐⭐⭐⭐minikube / kind本地开发、快速验证⭐⭐⭐云厂商托管ACK/EKS 等云上生产⭐⭐⭐⭐本文选用kubeadm——Kubernetes 官方标准工具兼容性最好文档最全。3. 系统初始化以下操作在模板机上执行之后通过 VMware 完全克隆生成三台节点再分别修改主机名和 IP。这样只需配置一次三台机器环境完全一致。3.1 换源国内访问 Ubuntu 官方源速度很慢换成华为云和阿里云的镜像。[rootubuntu2404 ~]# cat /etc/apt/sources.list.d/ubuntu.sources EOF Types: deb URIs: http://mirrors.huaweicloud.com/ubuntu/ Suites: noble noble-updates noble-backports Components: main restricted universe multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg EOF添加 containerd 和 Kubernetes 仓库[rootubuntu2404 ~]# curl -fsSL https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu/gpg | \ gpg --dearmour -o /etc/apt/trusted.gpg.d/containerd.gpg [rootubuntu2404 ~]# cat EOF /etc/apt/sources.list.d/docker-ce.list deb [archamd64] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu noble stable EOF ​ [rootubuntu2404 ~]# curl -fsSL https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/Release.key | \ gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg [rootubuntu2404 ~]# echo deb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/deb/ / \ /etc/apt/sources.list.d/kubernetes.list3.2 安装基础软件[rootubuntu2404 ~]# apt update apt install -y vim lrzsz bash-completion \ open-vm-tools apt-transport-https sshpass chrony3.3 网络配置[rootubuntu2404 ~]# cat /etc/netplan/00-static.yaml EOF network: ethernets: ens33: dhcp4: no addresses: - 10.1.8.30/24 routes: - to: default via: 10.1.8.2 nameservers: addresses: - 10.1.8.2 - 223.5.5.5 version: 2 EOF [rootubuntu2404 ~]# chmod 600 /etc/netplan/00-static.yaml [rootubuntu2404 ~]# netplan apply这里 IP 先写成10.1.8.30克隆后再根据实际角色改。配置 /etc/hosts让三台机器能通过主机名互相访问[rootubuntu2404 ~]# cat EOF /etc/hosts ​ ###### kubernetes ##### 10.1.8.30 master30.k8s.local master30 10.1.8.31 worker31.k8s.local worker31 10.1.8.32 worker32.k8s.local worker32 EOF3.4 内核参数Kubernetes 依赖 IPVS 做负载均衡、overlay/bridge 做容器网络需要加载对应内核模块并调整参数。# 1. 关闭 swapKubernetes 硬性要求 [rootubuntu2404 ~]# swapoff -a sed -i /^.*swap/d /etc/fstab rm -f /swap.img ​ # 2. 安装 IPVS 依赖包 [rootubuntu2404 ~]# apt install -y iptables ipvsadm ipset conntrack ​ # 3. 临时加载内核模块立即生效 [rootubuntu2404 ~]# modprobe overlay br_netfilter [rootubuntu2404 ~]# modprobe ip_vs ip_vs_rr ip_vs_wrr ip_vs_lc ip_vs_sh nf_conntrack ​ # 4. 永久加载重启后自动生效 [rootubuntu2404 ~]# cat /etc/modules-load.d/k8s-net.conf EOF br_netfilter overlay ip_vs ip_vs_rr ip_vs_wrr ip_vs_lc ip_vs_sh nf_conntrack EOF ​ # 5. 内核参数 [rootubuntu2404 ~]# cat /etc/sysctl.d/k8s.conf EOF net.bridge.bridge-nf-call-iptables1 net.bridge.bridge-nf-call-ip6tables1 net.ipv4.ip_forward1 vm.swappiness0 EOF [rootubuntu2404 ~]# sysctl -p /etc/sysctl.d/k8s.conf各参数含义bridge-nf-call-iptables让 Linux 网桥的流量经过 iptables 过滤K8s 网络必需ip_forward1开启路由转发swappiness0禁用 swap 的使用倾向3.5 SSH 配置[rootubuntu2404 ~]# echo UseDNS no /etc/ssh/sshd_config [rootubuntu2404 ~]# echo StrictHostKeyChecking no /etc/ssh/ssh_config [rootubuntu2404 ~]# ssh-keygen -N -f ~/.ssh/id_rsa -t rsa [rootubuntu2404 ~]# sshpass -p 123 ssh-copy-id rootlocalhost3.6 配置 containerd[rootubuntu2404 ~]# apt install -y containerd.io1.7.20-1 cri-tools ​ # 生成默认配置 [rootubuntu2404 ~]# containerd config default /etc/containerd/config.toml ​ # 两项关键修改 [rootubuntu2404 ~]# sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml [rootubuntu2404 ~]# sed -i s|sandbox_image .*|sandbox_image registry.k8s.io/pause:3.9| /etc/containerd/config.tomlSystemdCgroup true确保 containerd 使用 systemd 作为 cgroup 驱动与 kubelet 保持一致避免 cgroup 混乱。配置镜像加速国内必备否则拉镜像极慢甚至失败[rootubuntu2404 ~]# vim /etc/containerd/config.toml 找到 [plugins.io.containerd.grpc.v1.cri.registry.mirrors] 部分添加 [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://docker.m.daocloud.io,https://docker.1ms.run] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.registry.k8s.io] endpoint [https://k8s.m.daocloud.io,https://registry.cn-hangzhou.aliyuncs.com/google_containers]重启生效[rootubuntu2404 ~]# systemctl restart containerd3.7 安装 Kubernetes 组件[rootubuntu2404 ~]# apt install -y kubeadm1.30.2-1.1 kubelet1.30.2-1.1 kubectl1.30.2-1.1 [rootubuntu2404 ~]# systemctl enable kubelet --now此时systemctl status kubelet会显示activating——这是正常的。kubelet 在等kubeadm init生成/var/lib/kubelet/config.yaml没有这个文件它起不来。初始化集群后就会自动变为active。[rootubuntu2404 ~]# init 0 # 关机准备克隆3.8 克隆节点并修改网络用 VMware完全克隆出 3 台虚拟机。克隆完成后分别开机在每台机器上修改主机名和 IPmaster30 [rootubuntu2404 ~]# hostnamectl set-hostname master30.k8s.local # 修改 /etc/netplan/00-static.yamlIP 改为 10.1.8.30 [rootmaster30 ~]# netplan apply worker31 [rootubuntu2404 ~]# hostnamectl set-hostname worker31.k8s.local # 修改 /etc/netplan/00-static.yamlIP 改为 10.1.8.31 [rootworker31 ~]# netplan apply worker32 [rootubuntu2404 ~]# hostnamectl set-hostname worker32.k8s.local # 修改 /etc/netplan/00-static.yamlIP 改为 10.1.8.32 [rootworker32 ~]# netplan apply4. 初始化集群4.1 预拉取镜像初始化过程中需要下载 K8s 核心镜像提前拉取可以避免 init 时等太久。在master30上执行[rootmaster30 ~]# kubeadm config images pull --kubernetes-versionv1.30.2国内网络慢的话走阿里云镜像仓库[rootmaster30 ~]# kubeadm config images pull --kubernetes-versionv1.30.2 \ --image-repository registry.aliyuncs.com/google_containersWorker 节点至少需要 kube-proxy 和 pause 这两个镜像在worker31上执行[rootworker31 ~]# nerdctl pull registry.k8s.io/kube-proxy:v1.30.2 [rootworker31 ~]# nerdctl pull registry.k8s.io/pause:3.9在worker32上执行[rootworker32 ~]# nerdctl pull registry.k8s.io/kube-proxy:v1.30.2 [rootworker32 ~]# nerdctl pull registry.k8s.io/pause:3.94.2 kubeadm init——初始化控制平面在master30上执行[rootmaster30 ~]# kubeadm init \ --kubernetes-versionv1.30.2 \ --pod-network-cidr10.224.0.0/16关键参数--pod-network-cidrPod 网络范围不同 CNI 插件有不同要求。本文用 Calico后面会改成10.224.0.0/16--apiserver-advertise-address如果 master 有多张网卡建议显式指定 API Server 对外监听的 IP例如--apiserver-advertise-address10.1.8.30初始化成功后终端会输出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 ​ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 10.1.8.30:6443 --token mi0yt8.1tzza4q64dr8y3pc \ --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fd⚠️把最后那行 join 命令复制保存下来worker 加入集群全靠它。4.3 配置 kubectl 凭据在master30上执行[rootmaster30 ~]# mkdir -p $HOME/.kube [rootmaster30 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config此时可以查看节点状态——由于还没装网络插件节点是NotReady[rootmaster30 ~]# kubectl get nodesNAME STATUS ROLES AGE VERSION master30.k8s.local NotReady control-plane 2m v1.30.2kubectl 凭据查找优先级--kubeconfig命令行参数$KUBECONFIG环境变量~/.kube/config默认路径5. 部署 Calico 网络Kubernetes 本身不提供网络实现需要安装 CNI 网络插件。本文选用Calico——性能好、功能全、社区活跃。以下操作均在master30上执行。5.1 下载并修改配置[rootmaster30 ~]# wget --no-check-certificate \ https://raw.githubusercontent.com/projectcalico/calico/v3.30.7/manifests/calico.yaml确认集群的 Pod CIDR确保 Calico 配置与之一致[rootmaster30 ~]# kubectl get cm -n kube-system kubeadm-config -o yaml | grep podSubnetpodSubnet: 10.224.0.0/16[rootmaster30 ~]# sed -i s|# - name: CALICO_IPV4POOL_CIDR|- name: CALICO_IPV4POOL_CIDR|g calico.yaml [rootmaster30 ~]# sed -i s|# value: \192.*| value: \10.224.0.0/16\|g calico.yaml5.2 拉取 Calico 镜像在所有三台节点上分别执行[rootmaster30 ~]# nerdctl pull docker.io/calico/cni:v3.30.7 [rootmaster30 ~]# nerdctl pull docker.io/calico/node:v3.30.7 [rootmaster30 ~]# nerdctl pull docker.io/calico/kube-controllers:v3.30.7 [rootworker31 ~]# nerdctl pull docker.io/calico/cni:v3.30.7 [rootworker31 ~]# nerdctl pull docker.io/calico/node:v3.30.7 [rootworker31 ~]# nerdctl pull docker.io/calico/kube-controllers:v3.30.7 [rootworker32 ~]# nerdctl pull docker.io/calico/cni:v3.30.7 [rootworker32 ~]# nerdctl pull docker.io/calico/node:v3.30.7 [rootworker32 ~]# nerdctl pull docker.io/calico/kube-controllers:v3.30.75.3 部署并验证[rootmaster30 ~]# kubectl apply -f calico.yaml[rootmaster30 ~]# kubectl get pods -ANAMESPACE NAME READY STATUS kube-system calico-kube-controllers-56fcbf9d6b-v6qsn 1/1 Running kube-system calico-node-vc9v6 1/1 Running kube-system coredns-6d8c4cb4d-9qdxg 1/1 Running kube-system coredns-6d8c4cb4d-wwfmx 1/1 Running kube-system etcd-master30.k8s.local 1/1 Running kube-system kube-apiserver-master30.k8s.local 1/1 Running kube-system kube-controller-manager-master30.k8s.local 1/1 Running kube-system kube-proxy-8b7tn 1/1 Running kube-system kube-scheduler-master30.k8s.local 1/1 Running所有 control-plane pod calico-node CoreDNS 都Running网络就绪。此时再查节点状态[rootmaster30 ~]# kubectl get nodesNAME STATUS ROLES AGE VERSION master30.k8s.local Ready control-plane 5m v1.30.2NotReady→Ready搞定。6. 加入 Worker 节点使用刚保存的 join 命令在每台 worker 上执行在worker31上执行[rootworker31 ~]# kubeadm join 10.1.8.30:6443 --token mi0yt8.1tzza4q64dr8y3pc \ --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fd在worker32上执行[rootworker32 ~]# kubeadm join 10.1.8.30:6443 --token mi0yt8.1tzza4q64dr8y3pc \ --discovery-token-ca-cert-hash sha256:5606e09618330aee8859abe3ea4cd8734f9b540630048a6e1c3aaf6c54d486fdToken 默认24 小时过期。如果忘了保存 join 命令在 master 上重新生成在master30上执行[rootmaster30 ~]# kubeadm token create --print-join-command7. 验证集群在master30上执行[rootmaster30 ~]# kubectl cluster-infoKubernetes control plane is running at https://10.1.8.30:6443[rootmaster30 ~]# kubectl versionClient Version: v1.30.2 Server Version: v1.30.2[rootmaster30 ~]# kubectl get nodesNAME STATUS ROLES AGE VERSION master30.k8s.local Ready control-plane 9h v1.30.2 worker31.k8s.local Ready none 8h v1.30.2 worker32.k8s.local Ready none 8h v1.30.2三节点全部Ready集群部署完成。8. 节点管理8.1 查看节点详情在master30上执行[rootmaster30 ~]# kubectl get nodes [rootmaster30 ~]# kubectl describe node worker31.k8s.local8.2 驱逐并删除一个 Worker 节点假设要下线 worker31在master30上执行前三步# 1. 驱逐 Pod——把 worker31 上的 Pod 迁移到其他节点 [rootmaster30 ~]# kubectl drain worker31.k8s.local --ignore-daemonsetsDaemonSet 类型的 Pod如 calico-node、kube-proxy每个节点一份不驱逐用--ignore-daemonsets跳过。# 2. 确认节点已进入维护模式 [rootmaster30 ~]# kubectl get nodesworker31.k8s.local Ready,SchedulingDisabled ...# 3. 从集群中删除 [rootmaster30 ~]# kubectl delete node worker31.k8s.local然后 SSH 到worker31上清理残留[rootworker31 ~]# kubeadm reset -f8.3 删除整个集群按顺序操作先清 worker再清 master。在master30上执行# 驱逐并删除所有 worker [rootmaster30 ~]# kubectl drain worker31.k8s.local --ignore-daemonsets --force [rootmaster30 ~]# kubectl drain worker32.k8s.local --ignore-daemonsets --force [rootmaster30 ~]# kubectl delete node worker31.k8s.local worker32.k8s.local在worker31和worker32上分别重置[rootworker31 ~]# kubeadm reset -f [rootworker32 ~]# kubeadm reset -f回到master30备份配置后删除自己# 可选备份集群配置方便重建 [rootmaster30 ~]# kubectl get cm kubeadm-config -n kube-system -o yaml kubeadm.yml编辑 kubeadm.yml删掉非必要的字段保留核心配置apiServer、apiVersion、certificatesDir、clusterName、controllerManager、dns、etcd、imageRepository、kind、kubernetesVersion、networking、scheduler。# 删除 master 节点并重置 [rootmaster30 ~]# kubectl delete node master30.k8s.local [rootmaster30 ~]# kubeadm reset -f [rootmaster30 ~]# rm -rf ~/.kube/8.4 重建集群在master30上执行# 使用备份的配置文件重建 [rootmaster30 ~]# kubeadm init --config kubeadm.yml # 或者直接用原始命令 [rootmaster30 ~]# kubeadm init --kubernetes-versionv1.30.2 --pod-network-cidr10.224.0.0/16 # 配置凭据和网络 [rootmaster30 ~]# mkdir -p $HOME/.kube [rootmaster30 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config [rootmaster30 ~]# kubectl apply -f calico.yaml在worker31和worker32上用新的 join 命令重新加入[rootworker31 ~]# kubeadm join 10.1.8.30:6443 --token 新token \ --discovery-token-ca-cert-hash sha256:新hash [rootworker32 ~]# kubeadm join 10.1.8.30:6443 --token 新token \ --discovery-token-ca-cert-hash sha256:新hash9. Namespace 管理Namespace 把物理集群逻辑上划分成多个虚拟集群实现资源隔离。多团队共用一套集群时靠 Namespace 划分各自的地盘。9.1 默认 NamespaceKubernetes 创建了四个默认 NamespaceNamespace用途default不指定 ns 时的默认落脚点kube-system系统组件kube-proxy、CoreDNS、Calico 等kube-public所有用户含未认证可读的公共资源kube-node-lease节点心跳租约用于故障检测注意大多数资源Pod、Service、PVC 等属于某个 Namespace但Node 和 PersistentVolume 是集群级资源不在任何 Namespace 中。default和kube-system不可删除。9.2 基本操作在master30上执行[rootmaster30 ~]# kubectl get ns [rootmaster30 ~]# kubectl create ns webapp # 也可以用 YAML 创建 [rootmaster30 ~]# cat EOF | kubectl apply -f - apiVersion: v1 kind: Namespace metadata: name: webapp EOF # 在指定 ns 中创建 Pod [rootmaster30 ~]# kubectl run nginx --imagenginx -n webapp # 查看 ns 详情 [rootmaster30 ~]# kubectl describe ns webapp # 删除 ns——会级联删除其中所有资源 [rootmaster30 ~]# kubectl delete ns webapp9.3 切换默认 Namespace每次敲-n webapp很烦直接切到目标 ns方法一kubectl 自带[rootmaster30 ~]# kubectl config get-contextsCURRENT NAME ... NAMESPACE * kubernetes-adminkubernetes ... ← 空表示 default[rootmaster30 ~]# kubectl config set-context --current --namespacewebapp [rootmaster30 ~]# kubectl config set-context --current --namespacedefault # 切回方法二kubens推荐比 kubectl 简洁很多[rootmaster30 ~]# wget https://codeload.github.com/ahmetb/kubectx/zip/refs/heads/master -O kubectx.zip [rootmaster30 ~]# unzip kubectx.zip [rootmaster30 ~]# cp kubectx-master/kubens /usr/local/bin/ [rootmaster30 ~]# chmod x /usr/local/bin/kubens [rootmaster30 ~]# kubens # 列出所有 ns [rootmaster30 ~]# kubens kube-system # 切到 kube-system [rootmaster30 ~]# kubens - # 切回上一个 ns [rootmaster30 ~]# kubens -c # 查看当前 ns10. Context 与多集群切换10.1 理解 ~/.kube/configkubectl 的配置文件由三部分组成clusters集群地址 CA 证书users用户证书 私钥contexts把 cluster user namespace 三者绑在一起一键切换在master30上执行[rootmaster30 ~]# kubectl config viewapiVersion: v1 kind: Config current-context: kubernetes-adminkubernetes clusters: - name: kubernetes cluster: certificate-authority-data: base64编码的CA证书 server: https://10.1.8.30:6443 users: - name: kubernetes-admin user: client-certificate-data: base64编码的客户端证书 client-key-data: base64编码的私钥 contexts: - name: kubernetes-adminkubernetes context: cluster: kubernetes user: kubernetes-admin10.2 多集群配置示例假如你要同时管理两个集群或同一个集群用两个身份可以自定义 config 文件在master30上写入~/.kube/configapiVersion: v1 kind: Config current-context: ctx-cluster1 # 默认使用这个 context clusters: - name: cluster1 cluster: server: https://10.1.8.30:6443 certificate-authority-data: base64 - name: cluster2 cluster: server: https://10.1.8.30:6443 certificate-authority-data: base64 users: - name: cluster-admin user: client-certificate-data: base64 client-key-data: base64 contexts: - name: ctx-cluster1 context: cluster: cluster1 user: cluster-admin namespace: default - name: ctx-cluster2 context: cluster: cluster2 user: cluster-admin namespace: default这里两个 context 共享同一个用户cluster-admin绑定不同 cluster。用kubectl config use-context一键切换操作目标。10.3 切换 Contextkubectl 自带[rootmaster30 ~]# kubectl config get-contextsCURRENT NAME CLUSTER AUTHINFO NAMESPACE * ctx-cluster1 cluster1 cluster-admin default ctx-cluster2 cluster2 cluster-admin default[rootmaster30 ~]# kubectl config use-context ctx-cluster2 # 切换kubectx推荐和 kubens 同一个包[rootmaster30 ~]# cp kubectx-master/kubectx /usr/local/bin/ [rootmaster30 ~]# chmod x /usr/local/bin/kubectx [rootmaster30 ~]# kubectx # 列出所有 context [rootmaster30 ~]# kubectx ctx-cluster2 # 切换 [rootmaster30 ~]# kubectx - # 切回上一个 [rootmaster30 ~]# kubectx -c # 查看当前10.4 通过命令构建多集群配置不想手写 YAML用kubectl config子命令一行行构建效果一样[rootmaster30 ~]# kubectl config set-cluster cluster1 \ --serverhttps://10.1.8.30:6443 \ --certificate-authority/etc/kubernetes/pki/ca.crt --embed-certstrue [rootmaster30 ~]# kubectl config set-cluster cluster2 \ --serverhttps://10.1.8.30:6443 \ --certificate-authority/etc/kubernetes/pki/ca.crt --embed-certstrue [rootmaster30 ~]# kubectl config set-credentials cluster-admin \ --client-certificate/etc/kubernetes/pki/apiserver-kubelet-client.crt \ --client-key/etc/kubernetes/pki/apiserver-kubelet-client.key --embed-certstrue [rootmaster30 ~]# kubectl config set-context ctx-cluster1 \ --clustercluster1 --usercluster-admin --namespacedefault [rootmaster30 ~]# kubectl config set-context ctx-cluster2 \ --clustercluster2 --usercluster-admin --namespacedefault [rootmaster30 ~]# kubectl config use-context ctx-cluster111. 总结本文从零开始走完了以下流程步骤内容操作位置系统初始化换源、关 swap、内核模块、containerd、kubeadm模板机克隆节点VMware 完全克隆改主机名和 IP三台各自kubeadm init初始化控制平面master30Calico部署 CNI 网络三节点 Readymaster30 workers加入节点worker 执行 join 命令worker31、worker32节点管理驱逐、删除、重置、重建master30 workersNamespace资源隔离与切换master30Context多集群/多身份切换master30掌握了这些一套标准的三节点 K8s 集群就能稳定运行。后续可以继续探索 Pod、Deployment、Service、Ingress 等工作负载的玩法。