kubeadm 公网环境搭建 kubenetes 集群
Lapin Gris Lv3

环境介绍

最近手里闲置了两台云服务器,准备搭建一个公网环境下的 Kubenetes 集群,平时可以利用这个环境学习测试 k8s。公网搭建和本地搭建核心流程区别不大,要注意的是机器的公网IP以及在安全组里放行 kubenetes 组件必要的端口。

厂商 配置 k8s用途
阿里云 2c2g node
京东云 2c4g master

配置云服务器

配置公网 IP

云厂商的 ECS 都有分配一个公网 IP。这个公网 IP 在控制台上会显示,但是 IP 并不是直接配置在 ECS 机器上。

在机器上通过 ip a 命令只能看到内网 IP,我们需要在 ECS 设置一个虚拟网卡,将控制台的公网 IP 配置在 ECS 上。

将公网 IP 配置到 eth0 网卡上(master and node),

# 将 x.x.x.x 替换为机器公网IP
ip addr add x.x.x.x/24 dev eth0 label eth0:0
ip link set dev eth0:0 up

命令含义是为 eth0 网卡设置一个别名,eth0:0,将 ip 配置在这个别名上。

添加完成后,可以看到如下 eth0 下面多了 ipv4 的 IP。

Assign Public IP to eth0

Tips: 如果 IP 配置错了,等价删除命令 ip addr del x.x.x.x/24 dev eth0:0

放行端口

云服务器很多端口默认关闭的,需要在控制台打开

端口号 组件 理由
6443 apiserver 放行 master apiserver 端口

端口是否开放可以通过 telnet [IP] [端口] 的方式测试,

Test Port Open via Telnet

关闭 firewalld

systemctl stop firewalld
systemctl disable firewalld

安装 containerd

安装 containerd 并生成默认配置,

# 配置源
dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo


# 安装
yum install -y containerd

# 生成默认配置
containerd config default > /etc/containerd/config.toml

# 修改pause镜像为阿里云镜像地址
sed -i 's|registry.k8s.io/pause|registry.aliyuncs.com/google_containers/pause|' /etc/containerd/config.toml
# 启用 systemd cgroup
sed -i 's|SystemdCgroup = false|SystemdCgroup = true|' /etc/containerd/config.toml

# 重启
systemctl restart containerd

注意:请确保你已经将 runc options SystemdCgroup 配置修改为 true

否则,你可能会在启用了 cgroupv2 操作系统上,遇到如下报错,导致 pod 被 kubelet 重建

Pod sandbox changed, it will be killed and re-created.

安装 kubenetes

安装 kubenetes 1.31,

# 配置 kubenetes 源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/core:/stable:/v1.31/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.31/rpm/repodata/repomd.xml.key
EOF

# 安装
yum install -y kubelet kubeadm kubectl

安装 crictl

安装 crictl 工具,crictl 是一个很方便的工具,

# 安装 crictl
yum install cri-tools -y

# 生成 crictl 配置,
cat > /etc/crictl.yaml << EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 2
debug: false
pull-image-on-create: false
EOF

kubenetes 部署

从现在开始,部署 k8s 集群正式开始!

生成 init 配置

这里使用的是直接配置 yaml 的方式来部署集群,没有采用命令行,

kubeadm config print init-defaults > kubeadm-init.yaml

修改 init 配置,主要修改地方有 4 处,设置公网 IP,设置主机名,修改阿里云镜像源,新增一个 podSubnet 的条目,这里在后面的 CNI 网络要用到。

apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: x.x.x.x # 修改为master公网ip
bindPort: 6443
nodeRegistration:
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
name: k8s-master # 修改为主机名
taints: null
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.aliyuncs.com/google_containers # 修改国内镜像源
kind: ClusterConfiguration
kubernetesVersion: 1.28.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16 # 新增-指定CNI使用的网段(此处是 flannel 默认网段)
scheduler: {}

集群初始化

初始化集群之前,先加载 iptables 所需模块,开启 ip_forward,

modprobe br_netfilter
echo 1 > /proc/sys/net/ipv4/ip_forward

通过如下方式,持久化配置,实现开机自动加载

tee /etc/modules-load.d/br_netfilter.conf <<EOF
br_netfilter
EOF

tee /etc/sysctl.d/99-ipv4-ip-forward.conf <<EOF
net.ipv4.ip_forward = 1
EOF

加载完模块后后,初始化集群,

kubeadm init --config kubeadm-init.yaml --v 5

集群初始化完成后,将这条命令保存到 ~/.bashrc 中,方便后续通过 kubectl 命令管理集群。

export KUBECONFIG=/etc/kubernetes/admin.conf

执行完这一步,集群所需的关里面组件已经 up,此时集群依然是 not-ready 状态,应为我们还差集群网络没有配置,配置完毕后,集群状态会变为 ready。

[root@k8s-master ~]# kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system etcd-k8s-master 1/1 Running 9 14s
kube-system kube-apiserver-k8s-master 1/1 Running 9 12s
kube-system kube-controller-manager-k8s-master 1/1 Running 11 12s
kube-system kube-scheduler-k8s-master 1/1 Running 10 12s

集群网络配置 flannel

使用 flannel 0.26.2 作为集群的网络方案

# 下载 flannel 配置
wget https://github.com/flannel-io/flannel/releases/download/v0.26.2/kube-flannel.yml

# 提前下载 flannel 所需镜像,使用 daocloud 源
# 不同版本 flannel 采用的镜像版本不同,镜像版本查看 kube-flannel.yml 文件即可
crictl pull m.daocloud.io/docker.io/flannel/flannel:v0.26.2
crictl pull m.daocloud.io/docker.io/flannel/flannel-cni-plugin:v1.6.0-flannel1

# 替换镜像地址
sed -i 's|docker.io|m.daocloud.io/docker.io|' kube-flannel.yml

# 执行
kubectl apply -f kube-flannel.yml

Node 节点加入集群

kubeadm 创建集群完成后,会升成一条 join 命令用于节点加入集群,如果这条命令没保存也没有关系。让 master 重新生成一个 token 即可。

master 执行,

[root@k8s-master ~]# kubeadm token create --print-join-command
kubeadm join x.x.x.x:6443 --token jpqqsk.ion4kc134qm2z8zv --discovery-token-ca-cert-hash sha256:f40dadc8070ff0218bcfe8530974937a95e3cd1e2d25cd5f865669ac3b40bdb1

node 执行(如果需要持久化,参考上文 master 部分),

modprobe br_netfilter
echo 1 > /proc/sys/net/ipv4/ip_forward

kubeadm join x.x.x.x:6443 --token jpqqsk.ion4kc134qm2z8zv --discovery-token-ca-cert-hash sha256:f40dadc8070ff0218bcfe8530974937a95e3cd1e2d25cd5f865669ac3b40bdb1

FAQ

如何 debug flannel 启动失败问题?

当集群 apiserver 正常时,通过查看 flannel pod 的 日志确认错误

kubectl logs kube-flannel-ds-xxxxx -n kube-flannel

Debug flannel with pod logs

登录到问题节点,通过 crictl logs [flannel-container] 查看 flannel 容器日志

Debug flannel with pod logs

参考

1、https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md

2、https://juejin.cn/post/7383894854152405043