K8s 三节点集群部署(Ubuntu 22.04 + Docker + Kubernetes 1.23 + Flannel)

环境:Ubuntu 22.04 ×3 | Docker 20.10.14 | Kubernetes v1.23.0 | Flannel v0.26.1 以下命令均以 root 身份执行。


节点规划

角色

IP

主机名

Master

192.168.7.70

master

Node1

192.168.7.71

node1

Node2

192.168.7.72

node2

## 部署前先了解这几件事

项目

说明

容器运行时

使用 Docker,kubelet 通过内置的 dockershim 与它对接,所以 criSocket 固定写 /var/run/dockershim.sock

k8s 镜像仓库

国内无法直连 gcr.io / registry.k8s.io,组件镜像统一从 registry.aliyuncs.com/google_containers 拉取

Docker 镜像加速

Docker Hub 上的镜像(如 flannel)通过 /etc/docker/daemon.json 的 registry-mirrors 加速

cgroup 驱动

Ubuntu 22.04 默认是 cgroup v2,Docker 与 kubelet 必须统一使用 systemd 驱动

执行范围

第一~三步:三台都执行;第四、六步:仅 master;第五步:仅 node1 / node2

镜像加速地址

文中用的是公共加速地址,如果你有自己的加速器地址,可自行替换对应位置


一、基础环境配置(三台都执行)

1. 设置主机名

 # 按节点执行对应的一条
 hostnamectl set-hostname master   # 在 192.168.7.70 上执行
 hostnamectl set-hostname node1    # 在 192.168.7.71 上执行
 hostnamectl set-hostname node2    # 在 192.168.7.72 上执行

2. 配置 hosts 解析

 # 三台都执行,让节点之间可以通过主机名互相访问
 cat >> /etc/hosts << EOF
 192.168.7.70 master
 192.168.7.71 node1
 192.168.7.72 node2
 EOF

3. 安装常用软件并关闭交换分区

 apt update
 apt install -y vim lrzsz unzip wget net-tools tree bash-completion telnet
 ​
 swapoff -a                     # 临时关闭 swap(k8s 要求)
 sed -i '/swap/s/^/#/' /etc/fstab   # 永久关闭:注释掉 swap 挂载项

4. 内核转发与网桥参数

 # k8s 网络依赖网桥流量能被 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
 EOF
 ​
 modprobe br_netfilter          # 先加载 br_netfilter 模块,否则上面的参数不生效
 sysctl --system                # 生效

5. 时间同步

 apt install -y ntpdate
 ntpdate ntp.aliyun.com
 timedatectl set-timezone Asia/Shanghai   # 时区设为上海

二、安装 Docker(三台都执行)

1. 清理旧包并安装依赖

 for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do apt-get remove -y $pkg; done
 apt update
 apt-get install -y ca-certificates curl gnupg lsb-release apt-transport-https software-properties-common

2. 添加 Docker 官方源(阿里云镜像)

 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | apt-key add -
 add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
 apt update

3. 安装指定版本 Docker

 # 20.10.14 与本教程的 k8s 1.23 + dockershim 搭配
 apt install -y docker-ce=5:20.10.14~3-0~ubuntu-jammy docker-ce-cli=5:20.10.14~3-0~ubuntu-jammy containerd.io

4. 配置镜像加速 + cgroup 驱动并启动

mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://0flxnlct2crdwm8pmt.xuanyuan.dev",
    "https://docker.m.daocloud.io",
    "https://docker.1ms.run"
  ],
  "exec-opts": ["native.cgroupdriver=systemd"]
}
EOF

systemctl daemon-reload
systemctl restart docker
systemctl enable docker

检查是否生效(应看到 Cgroup Driver: systemd 和上面的两个加速地址):

docker info | grep -iE 'Cgroup Driver|Registry Mirrors' -A3

三、安装 kubeadm / kubelet / kubectl 1.23(三台都执行)

1. 配置 Kubernetes apt 源(阿里云镜像)

apt-get install -y apt-transport-https ca-certificates curl
curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg
apt-key add /usr/share/keyrings/kubernetes-archive-keyring.gpg
echo "deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" > /etc/apt/sources.list.d/kubernetes.list
apt-get update

2. 安装 1.23.0 版本并锁定版本

apt-get install -y kubelet=1.23.0-00 kubeadm=1.23.0-00 kubectl=1.23.0-00

# 锁定版本,避免被自动升级
apt-mark hold kubelet kubeadm kubectl docker docker-ce docker-ce-cli

systemctl enable kubelet   # 开机自启(初始化前会不断重启,属正常现象)

四、Master 节点初始化集群(仅在 192.168.7.70 执行)

1. 生成初始化配置模板

cd /root
kubeadm config print init-defaults > init-config.yaml

2. 修改成下面的内容

vim init-config.yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: 192.168.7.70        # Master 节点 IP(API Server 对外地址)
  bindPort: 6443                        # API Server 端口
nodeRegistration:
  criSocket: /var/run/dockershim.sock   # 使用 Docker 时固定填这个(注意不要带 unix:// 前缀)
  imagePullPolicy: IfNotPresent         # 镜像已存在则不再重复拉取
  name: master                          # 节点名,与主机名保持一致
  taints: null                          # 允许 Master 调度业务 Pod(不让调度则保留默认污点)
---
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: 1.23.0
imageRepository: registry.aliyuncs.com/google_containers   # k8s 组件镜像仓库(国内可用)
networking:
  dnsDomain: cluster.local
  serviceSubnet: 10.96.0.0/12           # Service 网段
  podSubnet: 10.244.0.0/16              # Pod 网段,需与后面 Flannel 的默认网段一致
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
cgroupDriver: systemd                   # 与 Docker 的 cgroup 驱动保持一致

3. 拉取集群所需镜像

kubeadm config images pull --config=/root/init-config.yaml

4. 初始化集群

kubeadm init --config=/root/init-config.yaml

初始化成功后会输出一条 join 命令,请复制保存(默认 24 小时有效):

kubeadm join 192.168.7.70:6443 --token <你的token> \
        --discovery-token-ca-cert-hash sha256:<你的hash>

5. 配置 kubectl 认证(root 用户)

mkdir -p /root/.kube
cp -f /etc/kubernetes/admin.conf /root/.kube/config
chmod 600 /root/.kube/config

kubectl get nodes   # 此时是 NotReady,装完网络插件后会变成 Ready

其他用户使用:把 /etc/kubernetes/admin.conf 拷到自己的 ~/.kube/config 并改属主; 或临时用 export KUBECONFIG=/etc/kubernetes/admin.conf。


五、Node 节点加入集群(在 192.168.7.71、192.168.7.72 执行)

# 直接执行 Master 初始化时输出的 join 命令
kubeadm join 192.168.7.70:6443 --token <你的token> \
        --discovery-token-ca-cert-hash sha256:<你的hash>

提示 This node has joined the cluster 即成功。

  • token 过期就在 master 重新生成:kubeadm token create --print-join-command

  • 回到 master 查看:kubectl get nodes


六、安装 Flannel 网络插件(仅 master 执行)

作用:给 Pod 分配 IP 并打通跨节点通信。不装它,节点会一直 NotReady、CoreDNS 会 Pending。

1. 下载 kube-flannel.yml

cd /root

# 使用 v0.26.1 版本(镜像在 Docker Hub,可走 daemon.json 里的加速源)
# 直连 GitHub 受限时,用 ghproxy 代理下载
curl -fsSL -o kube-flannel.yml https://ghproxy.net/https://raw.githubusercontent.com/flannel-io/flannel/v0.26.1/Documentation/kube-flannel.yml

2. 确认镜像与网段

grep -n 'image:' kube-flannel.yml              # 应为 docker.io/flannel/...
grep -n 'Network' kube-flannel.yml | head -3   # 应为 10.244.0.0/16(与 podSubnet 一致)

3. 应用配置

kubectl apply -f kube-flannel.yml

4. 等待就绪(首次需拉取镜像,约 1~3 分钟)

# Pod 会经历 Init:0/2 → Init:1/2 → Running,属正常过程
kubectl get pods -n kube-flannel -o wide
kubectl get nodes

预期结果:三台节点状态均为 Ready,flannel 的三个 DaemonSet Pod 均为 Running。


七、验证集群(可选)

# 部署一个 3 副本的 nginx
kubectl create deployment nginx-test --image=nginx:latest --replicas=3
kubectl get pods -o wide      # 副本 Running,且分散在不同节点,说明网络正常

# 暴露服务
kubectl expose deployment nginx-test --port=80 --type=NodePort
kubectl get svc               # 记下 NodePort(30000-32767),浏览器访问 http://节点IP:端口

八、安装 KubePi 面板(可选,仅 master 执行)

docker pull 1panel/kubepi
docker run --privileged -d --restart=unless-stopped -p 80:80 1panel/kubepi

浏览器访问 http://192.168.7.70,默认账号 admin,密码 kubepi; 在面板中导入 kubeconfig(/root/.kube/config)即可图形化管理集群。


九、常用运维命令

 # 状态查看
 kubectl get nodes -o wide
 kubectl get pods -A -o wide
 kubectl describe pod -n <命名空间> <pod名>     # 排查看事件
 kubectl logs -n <命名空间> <pod名>             # 看容器日志
 ​
 # 重新生成加入命令
 kubeadm token create --print-join-command
 ​
 # 节点下线 / 重置
 kubectl drain <节点名> --delete-emptydir-data --ignore-daemonsets   # 在 master 上先驱逐
 kubectl delete node <节点名>                                       # 再删除节点
 kubeadm reset                                                      # 在该节点上清理本地配置
 ​
 # Docker 配置
 docker info | grep -iE 'Cgroup Driver|Registry Mirrors'            # 检查驱动与加速源
 vim /etc/docker/daemon.json                                        # 改完执行:
 systemctl daemon-reload && systemctl restart docker
 ​
 # 重新初始化集群(慎用,会清空集群)
 kubeadm reset -f && kubeadm init --config=/root/init-config.yaml