操作成功度:
- 99.9%
部署耗时:
- 20分钟
环境及组件版本说明:
- 操作系统:Ubuntu 22.04.5 LTS
- 服务器:两台 4C4G 腾讯云轻量应用服务器
- 网络:两台服务器在两个账号下,无法内网互联,通过公网互通(仅限学习环境,生产不允许公网组建集群)
- IP栈:单协议栈 IPv4
- Kubernetes:v1.33.4(Latest)
- Containerd:v2.1.4(Latest)
- Flannel:v0.27.2(Latest)
转载说明:
- 原创内容,请注明出处
1. 环境配置
在所有机器上执行
1.1 技术方案选择说明
-
Why
Ubuntu 22.04.5 LTS
- 最热门的Linux发行版之一
- 易用性
- 成熟的社区资源
- LTS 长期支持版本足够稳定可靠
-
Why
Kubeadm
- K8s 官方推荐的部署方式
- 成熟的社区资源
- 上手能感受到部署的细节和集群核心参数
-
Why
Containerd
- K8s 官方力挺
- 轻量化,节省服务器资源
- 稳定性
- 提前适应新的技术方案,避免沉迷自己更加熟悉的技术(docker)
-
Why
Flannel
- 老牌知名网络插件
- 易用性
- 轻量化,节省服务器资源
- 简单经典,适合开源新手参与贡献
- 如果考虑参与开源贡献,选择经典且正在使用的项目是不错的选择
- 有必要了解
Go
云原生组件的开发模式,简单经典的组件易于上手
1.2 云服务器安全组设置
说明:
- 如果是单机部署集群可以跳过这一步
- 控制平面表中"必要性"仅适用于 单台 控制平面机器的情况,具体根据表中"使用者"衡量
1.2.1 控制面
协议 | 方向 | 端口范围 | 端口描述 | 使用者 | 必要性 |
---|---|---|---|---|---|
TCP | 入站 | 6443 | Kubernetes API 服务器 | 所有 | 必选 |
TCP | 入站 | 2379-2380 | etcd 服务器客户端 API | kube-apiserver、etcd | 可选 |
TCP | 入站 | 10250 | kubelet API | 自身、控制平面 | 必选(Metric需要) |
TCP | 入站 | 10259 | kube-scheduler | 自身 | 可选 |
TCP | 入站 | 10257 | kube-controller-manager | 自身 | 可选 |
1.2.2 工作节点
协议 | 方向 | 端口范围 | 端口描述 | 使用者 | 必要性 |
---|---|---|---|---|---|
TCP | 入站 | 10250 | kubelet API | 自身、控制面 | 必选 |
TCP | 入站 | 10256 | kube-proxy | 自身、负载均衡器 | 必选 |
TCP | 入站 | 30000-32767 | NodePort Services | 所有 | 可选(声明service时可以指定端口,防火墙只暴露指定的端口即可) |
UDP | 入站 | 30000-32767 | NodePort Services | 所有 | 可选(声明service时可以指定端口,防火墙只暴露指定的端口即可) |
1.3 设置 hostname
bash
# 控制平面机器执行
sudo hostnamectl hostname k8s-control
# 工作节点机器执行
sudo hostnamectl hostname k8s-worker-1
1.4 修改 hosts 文件
bash
sudo tee -a /etc/hosts <<EOF
<k8s-control public_ip> k8s-control
<k8s-worker-1 public_ip> k8s-worker-1
EOF
1.5 关闭交换分区与防火墙
bash
sudo swapoff -a # 暂时关闭交换分区
sudo sed -i '/swap/d' /etc/fstab # 保证重启后仍然生效
# 关闭操作系统防火墙,安装时建议,后续熟悉了可以精细化管理
sudo ufw disable
1.6 创建公网IP 的虚拟网卡
注意:如果所有机器之间可以使用内网互通,跳过此步
云服务商一般只会创建内网IP的虚拟网卡,因此在公网互通的环境下,需要我们手动创建公网IP的虚拟网卡, 在 所有 节点机器上执行如下命令:
bash
# 默认网卡新增公网IP
sudo nano /etc/netplan/01-netcfg.yaml
---内容如下
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses:
- <新增公网IP>/24 # 子网掩码255.255.255.0
---
# 应用配置
sudo netplan apply
# 重启网络服务
sudo systemctl restart systemd-networkd
# 检查 netplan 状态
sudo netplan status
# 检查 systemd-networkd 状态
sudo systemctl status systemd-networkd
1.7 内核配置
bash
# 加载bridge模块
sudo modprobe br_netfilter
# 持久化配置bridge模块
sudo tee /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF
# 设置所需的 sysctl 参数,参数在重新启动后保持不变
sudo tee /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
# 应用 sysctl 参数而不重新启动
sudo sysctl --system
# 验证配置的值是否为 1
sysctl net.bridge.bridge-nf-call-ip6tables
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.ipv4.ip_forward
1.8 同步所有节点的时间
bash
# 同步时间
sudo apt install -y chrony
sudo systemctl enable --now chrony
timedatectl set-timezone Asia/Shanghai
2. 安装配置 CRI(容器运行时)
在所有机器上执行
k8s v1.24之前可以跳过这一步,因为v1.24之前的 k8s 直接集成了 Docker Engine 的一个组件,名为 dockershim
2.1 cgroup 驱动选择
我们选择将 systemd
作为 cgroup 驱动,原因如下:
- 从 k8s v1.22 开始,在使用 kubeadm 创建集群时,如果用户没有在
KubeletConfiguration
下设置cgroupDriver
字段,kubeadm 默认使用systemd
- 在 k8s v1.33 中,启用
KubeletCgroupDriverFromCRI
特性门控结合支持RuntimeConfig
CRI RPC 的容器运行时,kubelet 会自动从运行时检测适当的 Cgroup 驱动程序,并忽略 kubelet 配置中的cgroupDriver
设置
因此我们要在 containerd
安装时,就选择 systemd 作为 Cgroup 驱动
2.2 安装 containerd
2.2.1 下载 containerd
并安装
从 github.com/containerd/... 下载二进制包,然后执行如下命令安装
bash
sudo tar Cxzvf /usr/local containerd-2.1.4-linux-amd64.tar.gz
2.2.2 下载并指定 systemd
为 cgroup
驱动
bash
sudo mkdir -p /usr/local/lib/systemd/system/
sudo wget -O /usr/local/lib/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service
sudo systemctl daemon-reload
sudo systemctl enable --now containerd
2.2.3 下载 runc
并安装
从 github.com/opencontain... 下载二进制包,然后执行如下命令安装
bash
sudo install -m 755 runc.amd64 /usr/local/sbin/runc
2.2.4 下载 CNI plugins
并安装
从 github.com/containerne... 下载二进制包,然后执行如下命令安装
bash
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.7.1.tgz
2.2.5 生成 containerd
默认配置
bash
sudo mkdir -p /etc/containerd
sudo touch /etc/containerd/config.toml
sudo bash -c 'containerd config default > /etc/containerd/config.toml'
2.2.6 国内镜像配置
www.cnblogs.com/plain-coder...
编辑 containerd
配置文件
bash
sudo nano /etc/containerd/config.toml
[plugins]
[plugins.'io.containerd.cri.v1.images']
...
[plugins.'io.containerd.cri.v1.images'.pinned_images]
sandbox = 'registry.aliyuncs.com/google_containers/pause:3.10'
[plugins.'io.containerd.cri.v1.images'.registry]
config_path = '/etc/containerd/certs.d'
...
配置路由
bash
# docker hub镜像加速
sudo mkdir -p /etc/containerd/certs.d/docker.io
sudo tee /etc/containerd/certs.d/docker.io/hosts.toml << EOF
server = "https://docker.io"
[host."https://dockerproxy.cn"]
capabilities = ["pull", "resolve"]
[host."https://docker.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF
# registry.k8s.io镜像加速
sudo mkdir -p /etc/containerd/certs.d/registry.k8s.io
sudo tee /etc/containerd/certs.d/registry.k8s.io/hosts.toml << 'EOF'
server = "https://registry.k8s.io"
[host."https://k8s.m.daocloud.io"]
capabilities = ["pull", "resolve", "push"]
EOF
# docker.elastic.co镜像加速
sudo mkdir -p /etc/containerd/certs.d/docker.elastic.co
sudo tee /etc/containerd/certs.d/docker.elastic.co/hosts.toml << 'EOF'
server = "https://docker.elastic.co"
[host."https://elastic.m.daocloud.io"]
capabilities = ["pull", "resolve", "push"]
EOF
# gcr.io镜像加速
sudo mkdir -p /etc/containerd/certs.d/gcr.io
sudo tee /etc/containerd/certs.d/gcr.io/hosts.toml << 'EOF'
server = "https://gcr.io"
[host."https://gcr.m.daocloud.io"]
capabilities = ["pull", "resolve", "push"]
EOF
# ghcr.io镜像加速
sudo mkdir -p /etc/containerd/certs.d/ghcr.io
sudo tee /etc/containerd/certs.d/ghcr.io/hosts.toml << 'EOF'
server = "https://ghcr.io"
[host."https://ghcr.m.daocloud.io"]
capabilities = ["pull", "resolve", "push"]
EOF
# quay.io镜像加速
sudo mkdir -p /etc/containerd/certs.d/quay.io
sudo tee /etc/containerd/certs.d/quay.io/hosts.toml << 'EOF'
server = "https://quay.io"
[host."https://quay.m.daocloud.io"]
capabilities = ["pull", "resolve", "push"]
EOF
# 默认镜像加速
sudo mkdir -p /etc/containerd/certs.d/_default
sudo tee /etc/containerd/certs.d/_default/hosts.toml << 'EOF'
[host."mirror.ccs.tencentyun.com"]
capabilities = ["pull", "resolve"]
EOF
2.2.7 重启 containerd
生效
bash
sudo systemctl restart containerd
3. 安装 kubeadm、kubelet 和 kubectl
在所有机器上执行
以下指令适用于 Kubernetes 1.33.
bash
sudo apt-get update
# apt-transport-https 可能是一个虚拟包(dummy package);如果是的话,你可以跳过安装这个包
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
# 如果 `/etc/apt/keyrings` 目录不存在,则应在 curl 命令之前创建它,请阅读下面的注释。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 此操作会覆盖 /etc/apt/sources.list.d/kubernetes.list 中现存的所有配置。
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
kubelet 现在每隔几秒就会重启,因为它陷入了一个等待 kubeadm 指令的死循环。
4. 修改 kubelet
参数
在所有机器上执行
bash
sudo nano /etc/default/kubelet
---内容如下
KUBELET_EXTRA_ARGS=--node-ip=<当前机器公网IP>
---
5. 初始化控制平面节点
***控制平面
机器上执行
5.1 kubeadm
初始化
如果初始化过程出错,可以执行sudo kubeadm reset -f
命令后,重新执行初始化
bash
# 说明: 10.244.0.0/16 是flannel特定要求的,其他组件按实际需求配置
# 节点之间通过内网通信的使用如下命令
sudo kubeadm init --apiserver-advertise-address=0.0.0.0 \
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.33.4 \
--pod-network-cidr=10.244.0.0/16 \
--upload-certs \
--v=5
# 节点之间通过公网通信的使用如下命令
sudo kubeadm init \
--apiserver-advertise-address=$(hostname -i) \ # 或者直接填入你的公网IP
--image-repository=registry.aliyuncs.com/google_containers \
--kubernetes-version=v1.33.4 \
--pod-network-cidr=10.244.0.0/16 \
--upload-certs \
--v=5
成功后,执行如下命令,允许非 root 用户运行 kubectl , 注意 :记得复制初始化完成后打印的工作节点 join
命令
bash
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
5.2 集群健康检查
bash
# 检查集群状态
kubectl cluster-info
# 健康检查
curl -k https://localhost:6443/healthz
5.3 修改kube-apiserver 配置
bash
sudo nano /etc/kubernetes/manifests/kube-apiserver.yaml
# 在 spec.containers.command 下添加`--bind-address`启动参数
--- 内容如下
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=****** # 你的公网IP
- --bind-address=0.0.0.0 # 增加这个
---
6. 安装网络插件
控制平面
机器上执行
bash
# 也可以在本地下载文件后上传到服务器使用
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
7. 添加工作节点
***工作节点
机器上执行 ***
执行第 5.1
步结尾复制的 kubeadm join
命令,类似如下格式
bash
sudo kubeadm join <控制平面公网IP>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>
8. 恭喜韩仙师

创作不易,希望大家多多支持,文章持续更新,我们下期见.
程序员白话 | [原创]
点关注不迷路
可以抖音搜索「程序员白话」,大家有任何问题都可以私聊我,知无不言~