单主三节点K8s集群搭建
环境规划
| 节点 | 主机名 | IP | 角色 | 系统 | 配置 |
|---|---|---|---|---|---|
| master | k8s-master | 192.168.10.10 | 控制平面(单主) | RedHat9.6 | 2C4G |
| node1 | k8s-node01 | 192.168.10.11 | 工作节点 | RedHat9.6 | 2C4G |
| node2 | k8s-node02 | 192.168.10.12 | 工作节点 | RedHat9.6 | 2C4G |
这里搭建集群用的是redhat9.6系列的Linux系统环境,其实也可适用其他系列如CentOS、Ubuntu等系列Linux系统环境,大同小异。但需要注意Linux内核与k8s版本之间的兼容性。
前置统一要求(3 台机器全部执行)
一、所有节点基础环境初始化
1. 关闭防火墙、SELinux、交换分区
# step1:关闭防火墙systemctl stop firewalld systemctl disable firewalld# step2:关闭selinuxsetenforce0sed-i's/^SELINUX=enforcing/SELINUX=disabled/'/etc/selinux/config# step3:永久关闭swap(k8s强制要求)swapoff-ased-i'/swap/s/^/#/'/etc/fstab# step4:重启一次所有主机init62. 主机名与 hosts 解析
# 分别在对应节点设置主机名hostnamectl set-hostname k8s-master&&bashhostnamectl set-hostname k8s-node1&&bashhostnamectl set-hostname k8s-node2&&bash# 所有节点写入hosts,IP地址改为你自己的规划的ipcat>>/etc/hosts<<EOF 192.168.10.10 k8s-master 192.168.10.11 k8s-node01 192.168.10.12 k8s-node02 EOF3. 内核加载 ipvs、网桥转发
# step1:加载内核模块modprobe overlay modprobe br_netfilter# step2:开启内核转发,将桥接的IPv4流量传递到iptables的链cat>>/etc/sysctl.d/k8s.conf<<EOF net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOFsysctl--system4. 时间同步
#step1:安装yuminstall-ychrony#step2:修改/etc/chrony.conf[root@k8s-master ~]# cat /etc/chrony.conf# Use public servers from the pool.ntp.org project.# Please consider joining the pool (https://www.pool.ntp.org/join.html).#pool 2.rhel.pool.ntp.org iburst 注释此行(无论市centos还是redhat)server ntp.aliyun.com iburst# 添加此行...........#step3:启动服务并设置开机自启systemctl start chronyd systemctlenablechronyd二、所有节点安装 containerd 和 docker
1. 安装 containerd、docker,此处安装参照了阿里云官方教程:
https://developer.aliyun.com/mirror/docker-ce)
# step 1: 安装必要的一些系统工具sudoyuminstall-yyum-utils# Step 2: 添加软件源信息#RedHatyum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/rhel/docker-ce.repo#CentOSyum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo# Step 3: 安装Dockersudoyuminstall-ydocker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# Step 4: 修改/etc/docker/daemon.json,配置镜像加速和关闭 Docker 的 cgroupstee/etc/docker/daemon.json<<-'EOF' { "exec-opts": ["native.cgroupdriver=systemd"], "registry-mirrors": [ "https://docker.1ms.run", "https://func.ink", "https://proxy.1panel.live", "https://docker-0.unsee.tech", "https://docker.zhai.cm", "https://a.ussh.net", "https://docker.melikeme.cn", "https://docker.hlmirror.com", "https://docker.xiaogenban1993.com", "https://docker.1panel.top", "https://docker.kejilion.pro", "https://dockerpull.cn", "https://docker.xuanyuan.me", "https://docker.anye.in", "https://hub.fast360.xyz" ] } EOF# Step 4: 开启Docker服务并设置开机自启systemctl daemon-reload systemctl start docker.service systemctlenabledocker.service# 注意:# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。# vim /etc/yum.repos.d/docker-ce.repo# 将[docker-ce-test]下方的enabled=0修改为enabled=1## 安装指定版本的Docker-CE:# Step 1: 查找Docker-CE的版本:# yum list docker-ce.x86_64 --showduplicates | sort -r# Loading mirror speeds from cached hostfile# Loaded plugins: branch, fastestmirror, langpacks# docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable# docker-ce.x86_64 17.03.1.ce-1.el7.centos @docker-ce-stable# docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable# Available Packages# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)# sudo yum -y install docker-ce-[VERSION]补充说明:新版 K8s(v1.24+)默认容器运行时是 containerd,不再默认、也不再原生支持 Docker Engine 作为运行时。
**K8s 1.20:**官方宣布弃用内置
dockershim(K8s 内置对接 Docker 的垫片),启动集群会打印警告Kubernetes。**K8s 1.24(2022 年):**彻底删除
dockershim,kubelet 不再内置兼容 Docker;
- 从此
kubeadm init默认自动识别、使用 containerd;- 云厂商 ACK/TKE/EKS/GKE 全部默认 containerd。
**当前(1.25~1.30):**containerd 是唯一主流默认运行时,CRI-O 是红帽系 OpenShift 默认。
**早年链路(1.23 及更早):**kubelet → dockershim(内置垫片)→ dockerd(Docker)→ containerd → runc(真正启动容器)
- 多层转发,冗余组件多、维护成本高。
- **现在标准链路(1.24+):**kubelet → containerd(原生实现 CRI 接口)→ runc
- 少一层转换,性能更好、架构简洁。
- **关键事实:**Docker Engine 底层本身就依赖 containerd;只是 Docker 多封装了 CLI、镜像仓库、网络等上层工具,不原生实现 K8s 需要的 CRI 标准接口。
如果后面有需要搭建cicd流水线和Harbor仓库,也可以在此安装docker,安装docker时必然会安装containerd,建议在此docker和containerd一并安装。
2. 生成默认配置并修改 cgroup 驱动
containerd config default>/etc/containerd/config.tomlcp/etc/containerd/config.toml{,.sample}sed-i's/SystemdCgroup \= false/SystemdCgroup \= true/g'/etc/containerd/config.toml# 替换镜像源(国内加速)sed-i's#registry.k8s.io#registry.aliyuncs.com/google#g'/etc/containerd/config.toml systemctl restart containerd三、所有节点安装 kubeadm、kubelet、kubectl
此处安装可参考https://developer.aliyun.com/mirror/kubernetes)。
1. 配置阿里云 k8s yum 源
#Step1:配置k8s repo源cat<<EOF|tee/etc/yum.repos.d/kubernetes.repo[kubernetes] name=Kubernetes baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/rpm/ enabled=1 gpgcheck=1 gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.36/rpm/repodata/repomd.xml.key #此处的版本号要与baseurl中的版本号对应 EOF#Step2yum clean all&&yum repolist#Step3:查看版本是否对应[root@k8s-master ~]# yum list|grep kuberneteskubeadm.x86_641.36.2-150500.2.1 @kubernetes kubectl.x86_641.36.2-150500.2.1 @kubernetes kubelet.x86_641.36.2-150500.2.1 @kubernetes.............对于k8s repo源baseurl中的版本号可在浏览器中访问https://mirrors.aliyun.com/kubernetes-new/core/stable查看其他k8s版本,然后根据自己想要安装的版本进行版本选择并修改baseurl。
2. 安装
yuminstall-ykubelet kubeadm kubectl#检验安装[root@k8s-master ~]# kubectl versionClient Version: v1.36.2 Kustomize Version: v5.8.1四、仅 Master 节点执行:初始化控制平面
1. kubeadm init 初始化(指定 apiserver 广告 IP、pod 网段、镜像仓库)
kubeadm init\--apiserver-advertise-address=192.168.10.10\--image-repository registry.aliyuncs.com/google_containers\--kubernetes-version v1.36.2\--service-cidr=10.96.0.0/12\--pod-network-cidr=10.244.0.0/16\--cri-socket unix:///var/run/containerd/containerd.sock#参数说明:--apiserver-advertise-address=192.168.10.10 控制平面apiserver 对外广播的IP,其他node节点通过这个IP连接集群;填master节点内网固定IP,不能填127.0.0.1。 --image-repository registry.aliyuncs.com/google_containers 指定K8s核心组件镜像仓库地址。kubeadm拉取kube-apiserver、etcd、pause、kube-controller-manager等镜像时会从这个仓库下载,国内替代官方registry.k8s.io,解决墙内拉取失败。 --kubernetes-version v1.36.2 指定本次初始化集群的Kubernetes版本,kubeadm会匹配下载对应版本控制平面镜像;版本必须和所有节点安装的 kubeadm/kubelet 版本一致。 --service-cidr=10.96.0.0/12 集群Service虚拟IP网段。集群内所有ClusterIP、NodePort、LoadBalancer服务的内网IP都从这个段分配,不能和宿主机、Pod 网段冲突,K8s默认固定网段。 --pod-network-cidr=10.244.0.0/16 Pod容器网络网段,交给CNI网络插件(Calico/Flannel)使用。示例10.244.0.0/16是 Calico 官方推荐网段,必须和 CNI 插件 yaml 里的网段保持一致,否则节点会 NotReady。 --cri-socket unix:///var/run/containerd/containerd.sock 告诉 kubeadm/kubelet 应该通过哪个 Unix Socket 文件与容器运行时对话。2. 配置 kubectl 权限(master)
mkdir-p$HOME/.kubesudocp-i/etc/kubernetes/admin.conf$HOME/.kube/configsudochown$(id-u):$(id-g)$HOME/.kube/config3. 保存kubeadm init初始化成功后输出的 join 命令(示例,以你实际输出为准)
kubeadmjoin192.168.10.10:6443--tokenxxxxxx\--discovery-token-ca-cert-hash sha256:xxxxxx- token 有效期 24h,过期重新生成:
kubeadm token create --print-join-command
五、所有 Node 节点执行:加入集群
1. 复制 master 输出的 join 命令,在 node1、node2 分别执行:
kubeadmjoin192.168.10.10:6443--tokenxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxx2. 加入集群成功后,建议对kubelet.service设置开机自启(所有节点)
systemctlenablekubelet.service3. 验证/查看集群
[root@k8s-master ~]# kubectl get nodesNAME STATUS ROLES AGE VERSION k8s-master NotReady control-plane 2m v1.36.2 k8s-node1 NotReady<none>10s v1.36.2 k8s-node2 NotReady<none>8s v1.36.2#可以看到集群状态目前还是NotReady状态。六、Master 节点安装网络插件 Calico(必须,否则节点 NotReady)
官网下载文档: (https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico-with-etcd-datastore),若出现版本兼容问题,可更换指定版本,尽量用较新的版本。
# Step1: 下载 calico 配置文件,可能会网络超时,保证网络通畅或试着科学上网下载curlhttps://raw.githubusercontent.com/projectcalico/calico/v3.32.0/manifests/calico.yaml-O# Step2: vim 修改 calico.yaml 文件中的 CALICO_IPV4POOL_CIDR 配置,# 取消注释并将value值改为kubeadm init初始化时--pod-network-cidr指定的IP网段10.244.0.0/16[root@k8s-master ~]# grep "CALICO_IPV4POOL_CIDR" -A 1 calico.yaml# - name: CALICO_IPV4POOL_CIDR# value: "192.168.0.0/16"1. 等待 3-5 分钟,在master节点查看节点状态
kubectl get nodes[root@k8s-master ~]# kubectl get nodesNAME STATUS ROLES AGE VERSION k8s-master Ready control-plane 32m v1.36.2 k8s-node1 Ready<none>20m v1.36.2 k8s-node2 Ready<none>20m v1.36.2# 全部变为 Ready 即集群搭建完成七、集群基础验证(master 执行)
# 查看节点kubectl get nodes# 查看集群组件状态kubectl get cs# 运行测试podkubectl create deployment nginx--image=nginx kubectl get pods-owide# 暴露服务测试访问kubectl expose deployment nginx--port=80--type=NodePort kubectl get svc对于kubectl get pods -o wide如果没有科学上网,大概率会出现ImagePullBackOff问题。若不想科学上网可查看我的另一篇博客k8s学习过程中遇到的问题记录和解决方法尝试解决。
八、在node节点使用 kubectl
node节点默认是不能使用kubectl命令的,具体原因不过多赘述。但为了学习方便,可以通过以下方法使得k8s-node1/2节点可以使用 kubectl
# Step1: 将 master 节点中将 /etc/kubernetes/admin.conf 拷贝到需要运行的服务器的 /etc/kubernetes 目录中scp/etc/kubernetes/admin.conf root@k8s-node1:/etc/kubernetesscp/etc/kubernetes/admin.conf root@k8s-node2:/etc/kubernetes# Step2: 在k8s-node1、k8s-node2上配置环境变量echo"export KUBECONFIG=/etc/kubernetes/admin.conf">>~/.bash_profilesource~/.bash_profile补充:安装 crictl (k8s集群各节点都建议安装)
官网下载:https://github.com/kubernetes-sigs/cri-tools
在 Kubernetes 集群中,kubelet通过 CRI 接口与容器运行时通信。crictl模拟了kubelet的行为,方便管理员:
- 调试容器运行时问题
- 查看和管理 Pod/容器
- 拉取镜像、查看镜像
- 排查 Pod 启动失败的原因
# 下载 crictl(使用最新稳定版)VERSION="v1.36.0"curl-L"https://github.com/kubernetes-sigs/cri-tools/releases/download/${VERSION}/crictl-${VERSION}-linux-amd64.tar.gz"-ocrictl.tar.gz# 解压并安装tar-zxvfcrictl.tar.gz-C/usr/local/bin/rm-fcrictl.tar.gz# 验证安装crictl--version# 配置 crictl 使用 containerdcat>/etc/crictl.yaml<<EOF runtime-endpoint: unix:///var/run/containerd/containerd.sock image-endpoint: unix:///var/run/containerd/containerd.sock timeout: 10 debug: false EOF# 测试crictl info crictlps-a#查看你之前创建k8s集群时所需要的所有镜像(拉取到的镜像)crictl images#docker images则看不到,原因在前面‘步骤二:安装container’中已经说明。