使用Kubeadm在Ubuntu22引导部署K8s公网集群

操作成功度

  • 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

参考: github.com/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 下载并指定 systemdcgroup 驱动

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. 恭喜韩仙师


创作不易,希望大家多多支持,文章持续更新,我们下期见.

程序员白话 | [原创]

点关注不迷路

可以抖音搜索「程序员白话」,大家有任何问题都可以私聊我,知无不言~

相关推荐
xiao-xiang30 分钟前
zookeeper-保姆级配置说明
分布式·zookeeper·云原生·中间件·zk
iFulling16 小时前
【云原生】CentOS安装Kubernetes+Jenkins
linux·云原生·kubernetes·centos·jenkins
Johny_Zhao1 天前
Conda、Anaconda、Miniconda对比分析
linux·网络安全·信息安全·kubernetes·云计算·conda·shell·containerd·anaconda·yum源·系统运维·miniconda
陈陈CHENCHEN1 天前
【Kubernetes】在 K8s 上部署 Alertmanager
kubernetes
斯普信专业组1 天前
Caddy + CoreDNS 深度解析:从功能架构到性能优化实践(上)
性能优化·架构·kubernetes·coredns
道一云黑板报1 天前
Spark云原生流处理实战与风控应用
大数据·ai·云原生·spark·kubernetes·ai编程
GGGGGGGGGGGGGG.1 天前
CI/CD 全链路实践:从 Git 基础到 Jenkins + GitLab 企业级部署
运维·git·ci/cd·云原生·gitlab·jenkins
退役小学生呀1 天前
十九、云原生分布式存储 CubeFS
分布式·docker·云原生·容器·kubernetes·k8s
香蕉割草机2 天前
云原生、容器及数据中心网络相关名词记录
网络·云原生