K8S部署

1、环境准备

系统初始化

设置主机名

# 在 Master 节点执行
hostnamectl set-hostname k8s-master

# 在 Worker 节点执行
hostnamectl set-hostname k8s-worker1

配置 Hosts 文件

在所有节点的 /etc/hosts 文件中添加节点信息

cat <<EOF | tee -a /etc/hosts
192.168.1.2 k8s-master
192.168.1.3 k8s-worker1
192.168.1.4 k8s-worker2
EOF

关闭 Swap 分区

首先查看系统是否已启用 Swap,确认设备或文件路径:

# 查看活跃的 Swap 设备/文件
swapon --show
# 或查看内存与 Swap 占用情况
free -h

临时关闭 Swap(立即生效)

swapoff -a

永久关闭 Swap(重启生效)

vim /etc/fstab
#注释 Swap 行
#或者直接执行下面语句
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

2、部署安装

安装 依赖

apt-get update
# apt-transport-https 可能是一个虚拟包(dummy package);如果是的话,你可以跳过安装这个包
apt-get install -y apt-transport-https ca-certificates curl gpg
#kimi提供
apt-get install -y apt-transport-https ca-certificates curl gpg socat conntrack ipset

写入内核模块配置

cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

加载内核模块

modprobe overlay
modprobe br_netfilter

确认模块是否加载

lsmod | grep -E 'overlay|br_netfilter'

将桥接的 IPv4 流量传递到 iptables 的链

cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

修改生效

sysctl --system

3、安装容器运行时

下载containerd并安装

选择版本:https://github.com/containerd/containerd/releasesopen in new window

#直接安装
apt install containerd
#或者选择版本下载安装
wget https://github.com/containerd/containerd/releases/download/v2.2.0/containerd-2.2.0-linux-amd64.tar.gz
tar Cxzvf /usr/local containerd-2.2.0-linux-amd64.tar.gz
wget https://raw.githubusercontent.com/containerd/containerd/v2.2.0/containerd.service
mv containerd.service /usr/lib/systemd/system/
systemctl daemon-reload
systemctl enable --now containerd

手动安装 containerd 2.2.x(指定版本)

# 下载 containerd 2.2.3
wget https://github.com/containerd/containerd/releases/download/v2.2.3/containerd-2.2.3-linux-amd64.tar.gz
# 解压到 /usr/local
tar Cxzvf /usr/local containerd-2.2.3-linux-amd64.tar.gz
# 下载 systemd 服务文件
wget https://raw.githubusercontent.com/containerd/containerd/v2.2.3/containerd.service
mv containerd.service /usr/lib/systemd/system/

# 启用并启动
systemctl daemon-reload
systemctl enable --now containerd

containerd配置文件

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml && \
grep 'SystemdCgroup' -B 11 /etc/containerd/config.toml
# 使用 sed 替换镜像源
sed -i 's|registry.k8s.io/pause:3.8|registry.aliyuncs.com/google_containers/pause:3.8|g' /etc/containerd/config.toml
systemctl daemon-reload
systemctl restart containerd.service

查看版本

containerd --version

如果手动安装runc

选择版本地址:https://github.com/opencontainers/runc/releasesopen in new window

chmod +x runc.amd64
mv runc.amd64 /usr/bin/runc
#查看runc版本号
runc -v

4、安装 kubernetes 工具

所有节点机器都执行。

安装 kubeadm、kubelet、kubectl 工具

  • kubectl: 用以控制集群的客户端工具
  • kubeadm: 用以构建一个 k8s 集群的官方工具
  • kubelet: 工作在集群的每个节点,负责容器的一些行为如启动
# 添加 Kubernetes 签名密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.35/deb/Release.key |gpg --dearmor -o /etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg
# 添加 Kubernetes 仓库
echo 'deb [signed-by=/etc/apt/trusted.gpg.d/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.35/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list
# 安装kubeadm、kubectl、kubelet
apt update
apt install kubelet=1.35.* kubeadm=1.35.* kubectl=1.35.*
apt-mark hold kubelet kubeadm kubectl

5、创建配置文件初始化集群

提前拉取了镜像

#查看所需镜像
kubeadm config images list --kubernetes-version=1.35.4
# 提前拉取镜像
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers
# 查看镜像
crictl images

kubeadm-config.yaml配置

apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
  # 修改为你的 Master 节点的 IP 地址
  advertiseAddress: 192.168.1.10
  bindPort: 6443
#nodeRegistration:
  # 忽略前置检查中的 Swap 错误(如果你没关 Swap)
  #ignorePreflightErrors:
    #- Swap
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
# 修改为阿里云镜像源,解决 CoreDNS 等镜像拉取慢的问题
imageRepository: registry.aliyuncs.com/google_containers
kubernetesVersion: v1.34.6
networking:
  # 【关键】Pod 网段,必须与 Calico 的默认配置匹配
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/12
  dnsDomain: cluster.local
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
# 允许 Kubelet 访问 cgroupfs 驱动
cgroupDriver: systemd

初始化 master 节点

不要在非 master 节点上运行 kubeadm init

# 初始化 kubeadm
kubeadm init --config=kubeadm-config.yaml --upload-certs
#--config=kubeadm-config.yaml: 使用我们刚才创建的配置文件。
#--upload-certs: 允许证书自动分发,方便后续 Worker 节点加入。
# 初始化 kubeadm
kubeadm init \
 --apiserver-advertise-address=192.168.0.210 \
 --image-repository registry.aliyuncs.com/google_containers \
 --kubernetes-version v1.35.4 \
 --service-cidr=10.96.0.0/12 \
 --pod-network-cidr=10.244.0.0/16
# 初始化 kubeadm
kubeadm init --image-repository registry.aliyuncs.com/google_containers
# 报错查看日志
systemctl status kubelet
journalctl -xeu kubelet

# 成功后按照提示执行
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
export KUBECONFIG=/etc/kubernetes/admin.conf
# 查看已加入的节点,k8s-master 节点执行
kubectl get nodes
# 查看集群状态,k8s-master 节点执行
kubectl get cs

初始化后记住下面Then you can join any number of worker nodes by running the following on each as root:下面信息

#将信息复制下来
kubeadm 192.168.0.210:6443 --token e7qjhz.cjbevut83kc001c8 \
        --discovery-token-ca-cert-hash sha256:50783ed23f76a59509a764b65b4e1f5adca9c850a3f87e0c64ca091279561052

如果错过初始化 Kubernetes 集群时输出的用于将其它节点加入集群的 kubeadm join 命令或者需要再次查看它。

可以在 master 节点通过以下方式来获取

添加 master 节点的命令获取方式

#24小时未过期的token查看获取
kubeadm token list
#获取前面拼接的sha256值
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^/sha256:/'

# 获取新的 certificate-key
kubeadm init phase upload-certs --upload-certs
# 生成添加 master 节点的命令
kubeadm token create --print-join-command --certificate-key <your-new-certificate-key>

添加 worker 节点的命令获取方式

# 添加 worker 节点的命令获取方式
kubeadm token create --print-join-command

初始化 worker 节点

kubeadm join 192.168.0.210:6443 --token e7qjhz.cjbevut83kc001c8 --discovery-token-ca-cert-hash sha256:50783ed23f76a59509a764b65b4e1f5adca9c850a3f87e0c64ca091279561052
# 配置 kubectl 命令工具
# https://github.com/chaseSpace/k8s-tutorial-cn/blob/main/install_by_kubeadm/install.md#55-%E5%9C%A8%E6%99%AE%E9%80%9A%E8%8A%82%E7%82%B9%E6%89%A7%E8%A1%8Ckubectl
# 普通节点执行 kubectl get nodes 提示错误:memcache.go:265] couldn't get current server API group list: Get "http://localhost:8080/api?timeout=32s": dial tcp [::1]:8080: connect: connection refused
mkdir ~/.kube && cp /etc/kubernetes/kubelet.conf  ~/.kube/config
# 执行完成后,可以尝试使用如下两条命令测试 kubectl 是否可用
# 查看已加入的节点,k8s-worker01 节点执行
kubectl get nodes
# 从主节点运行以下命令来检查节点状态,k8s-master 节点执行
kubectl get cs

现在有了 master 和 node 节点,但是所有节点状态都是 NotReady,这是因为没有 CNI 网络插件。

6、安装 CNI 网络插件

这里选择 Calico,注意版本需要匹配 k8s 版本,否则无法应用,查看支持的 k8s 版本open in new window

#编辑calico.yaml,去掉#
# - name: CALICO_IPV4POOL_CIDR
#   value: "10.244.0.0/16"
#Calico 只在 master 装一次,全集群自动生效
wget --no-check-certificate https://raw.githubusercontent.com/projectcalico/calico/v3.28.1/manifests/calico.yaml
kubectl apply -f calico.yaml
#calico镜像拉不动,卡住了,换国内镜像源
#先删除清空脏 CNI 配置(必须!)
kubectl delete -f calico.yaml
rm -rf /etc/cni/net.d/*
systemctl restart containerd
systemctl restart kubelet
# 修改为阿里云 Calico 镜像
sed -i 's|docker.io/calico/|registry.aliyuncs.com/calico/|g' calico.yaml
#修改华为的 Calico 镜像
sed -i 's#docker.io/calico/#swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/calico/#g' calico.yaml
kubectl apply -f calico.yaml
# 查看 pod 状态
kubectl get pods -n kube-system --watch
#查看 kube-system 命名空间下所有 Pod 的详细信息
kubectl get pods -n kube-system -o wide
# 报错看日志( Init:ImagePullBackOff )
kubectl describe pod calico-node-hv4ss -n kube-system
#检查镜像拉取情况
# 查看哪些镜像正在拉取或失败
kubectl get events -n kube-system --sort-by='.lastTimestamp' | tail -20
# 查看 pod 部署的所在 node
kubectl get pods -n kube-system -o wide
# 手动拉取镜像(在所有节点都执行)
export http_proxy=http://192.168.0.104:10809 && export https_proxy=http://192.168.0.104:10809 && export no_proxy="localhost, 127.0.0.1, ::1"
ctr -n k8s.io image pull docker.io/calico/cni:v3.28.1
ctr -n k8s.io image pull docker.io/calico/node:v3.28.1
ctr -n k8s.io image pull docker.io/calico/kube-controllers:v3.28.1
# 删除 Calico pod,让其重启
kubectl get pods -n kube-system | grep calico-node-hv4ss | awk '{print$1}'| xargs kubectl delete -n kube-system pods
kubectl describe po calico-node-hv4ss -n kube-system
# 防火墙中允许 Calico 端口,在所有节点上运行 ufw 命令
sudo ufw allow 179/tcp
sudo ufw allow 4789/udp
sudo ufw allow 51820/udp
sudo ufw allow 51821/udp
sudo ufw reload
# 验证 Calico pod 的状态,运行
kubectl get pods -n kube-system
# 查看 nodes 状态
kubectl get nodes

查看服务网段

kubectl get cm -n kube-system kubeadm-config -o yaml | grep serviceSubnet

查看 Pod 网段

kubectl get cm -n kube-system kubeadm-config -o yaml | grep podSubnet

一次性查看全部

kubectl get cm -n kube-system kubeadm-config -o yaml | grep -E 'podSubnet|serviceSubnet'

7、验证集群

节点导入离线镜像

ctr -n k8s.io images import nginx-alpine.tar

修改配置

#查看详细
kubectl get node -o wide

通过在集群中部署 nginx 服务来验证集群是否正常工作。

# 创建
kubectl create deployment nginx-test-deployment --image=nginx:alpine --replicas=2
# 通过 NodePort 类型的 Service 来暴露 Pod
kubectl expose deployment nginx-test-deployment --name=nginx-test-service --type NodePort --port 80 --target-port 80
# 查看 pod 及服务信息
kubectl get pod,svc
kubectl describe svc nginx-test-service
kubectl get pods -l app=nginx-test-deployment -o wide
kubectl get pod -o wide
kubectl get svc -o wide

# root@k8s-master:~/k8s/blog-in-kubernetes# kubectl get pod,svc
# NAME                                         READY   STATUS    RESTARTS      AGE
# pod/nginx-test-deployment-6876b4697f-68wnt   1/1     Running   0             13s
# pod/nginx-test-deployment-6876b4697f-dp66k   1/1     Running   0             13s
# 
# NAME                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# service/nginx-test-service   NodePort    10.102.158.74   <none>        80:31493/TCP   6s
# 它将容器 80 端口映射到【所有节点】的一个随机端口(这里是 31493 )。 我们通过访问节点端口来测试在所有集群机器上的 pod 的连通性。
# 在 k8s-master(192.168.0.210)上执行
curl http://192.168.0.210:31493
curl http://192.168.0.211:31493
# k8s-master shell 打不开,局域网其它机器(192.168.0.104)浏览器可以打开
curl http://k8s-worker01:31493
# 删除部署
kubectl delete deployment nginx-test-deployment
kubectl delete svc nginx-test-service
kubectl delete namespace ingress-nginx

8、其他问题

1、版本不一致解决

解锁

apt-mark unhold kubelet kubeadm kubectl

直接安装指定正确版本

apt-get install -y \
kubelet=1.35.* \
kubeadm=1.35.* \
kubectl=1.35.*

验证是否正确

kubeadm version
kubelet --version
kubectl version --client

再锁定版本

apt-mark hold kubelet kubeadm kubectl

2、CNI 插件目录问题

# 创建目录
mkdir -p /usr/lib/cni /opt/cni/bin
# 下载官方 CNI 插件包
CNI_VERSION="v1.6.2"
curl -L -o cni-plugins.tgz "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-amd64-${CNI_VERSION}.tgz"

# 解压到标准路径
tar -C /opt/cni/bin -xzf cni-plugins.tgz
ln -sf /opt/cni/bin/* /usr/lib/cni/

# 确认插件存在
ls -la /opt/cni/bin/
ls -la /usr/lib/cni/

# 在所有节点执行
systemctl restart containerd

# 在 master 节点删除卡住的 Pod,让它们重新创建
kubectl delete pod -n kube-system -l k8s-app=kube-dns
kubectl delete pod -n kube-system -l k8s-app=calico-kube-controllers

后续关键操作提醒

  • 令牌管理:初始化时生成的加入令牌默认 24 小时后过期。过期后,可在 Master 上 生成新命令。

    kubeadm token create --print-join-command
    
  • 集群升级:不可直接使用 apt upgrade。必须使用 kubeadm upgrade 进行规划式升级,并依次升级控制平面和工作节点。

  • 生产加固:考虑配置高可用控制平面、启用 RBAC、设置网络策略等。

后面计划搭建一个 NFS Server 的虚机,通过 NFS 提供 PVC 功能,然后基于 PVC 建设私有镜像仓库 Habor