使用 kubeadm 部署 kubernetes
本文介绍了使用kubeadm部署三节点Kubernetes集群(v1.32.5)的详细方案。采用CentOS Stream 9系统,包含1个master和2个worker节点,分别使用docker+cri-dockerd和containerd作为容器运行时。部署过程包括:配置阿里云yum源、系统初始化(关闭防火墙/selinux/swap)、加载ipvs模块、设置网络插件flannel(vxlan
使用 kubeadm 部署 kubernetes
1. 安装依赖
因为 kubernetes 版本和相关功能需要有指定的 linux 内核版本作为支撑,所以本次采用CentOS-Stream-9-20241007.0
内核版本5.14.0-514.el9.x86_64
进行部署。
操作系统及程序
程序 | 版本 |
---|---|
OS | CentOS-Stream-9-20241007.0 |
Linuex Kernel | 5.14.0-514.el9.x86_64 |
kubernetes | v1.32.5.x86_64 |
docker-ce | 24.0.9-1.el9.x86_64 |
containerd | 1.7.22-3.1.el9.x86_64 |
cri-docker | 0.3.20.el9.x86_64 |
flannel | v0.24.2 |
主机信息
节点 | ip |
---|---|
master1 | 192.167.16.116 |
node1 | 192.167.16.117 |
node2 | 192.167.16.118 |
网络信息
节点 | ip |
---|---|
Cluster IP CIDR | 10.244.0.0/16 |
Service Cluster IP CIDR | 10.96.0.0/15 |
Service DNS IP | 10.96.0.10 |
DNS DN | cluster.local |
2. 部署方案
本案例将部署一个三节点的 kubernetes 集群,1个 master + 2个 node。
因 Dockershim 在 Kubernetes v1.24 版本已经被移除,如果需要继续使用 docker 作为容器运行时,需要自行部署 cri-dockerd 对接 Kubernetes。
本案例中 master 和 node1 使用 docker + cri-dockerd 作为容器运行时,node2 使用 containerd 作为运行时。
本案例中使用 flannel vxlan 模式部署网络插件。
本案例中使用 阿里云开源镜像站
的相关 yum 源。
因国内镜像中心大多都已无法访问,本例中的所有镜像通过静态导入的方式提前进行导入。
2.2. 参考连接
2.3. 相关文件
kubernetes-1.32.5 镜像文件,flannel 镜像文件,cri-dockerd 安装文件:见夸克网盘:
https://pan.quark.cn/s/ae0218e88e9c
提取码:EiA2
3. 部署步骤
3.1. 初始化所有节点
配置相关 yum 源,此处都使用阿里云开源镜像站的源
# 配置阿里云 centos 7 yum 源
cat << 'EOF' | tee /etc/yum.repos.d/centos-stream.repo
[baseos]
name=CentOS Stream 9 - BaseOS - Aliyun
baseurl=https://mirrors.aliyun.com/centos-stream/9-stream/BaseOS/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
[appstream]
name=CentOS Stream 9 - AppStream - Aliyun
baseurl=https://mirrors.aliyun.com/centos-stream/9-stream/AppStream/x86_64/os/
gpgcheck=1
enabled=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-Official
EOF
# 配置阿里云 docker-ce yum 源
cat << 'EOF' | tee /etc/yum.repos.d/docker-ce.repo
[docker-ce-stable]
name=Docker CE Stable - $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/$basearch/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-stable-debuginfo]
name=Docker CE Stable - Debuginfo $basearch
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/debug-$basearch/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
[docker-ce-stable-source]
name=Docker CE Stable - Sources
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/$releasever/source/stable
enabled=0
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
# 配置阿里云 kubernetes yum 源
cat << 'EOF' | tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/repodata/repomd.xml.key
EOF
系统初始化:
- 安装基础依赖;
- 关闭防火墙,selinux
- 关闭 swap (在 1.22 版之前,由于在涉及swap时保证和计算 Pod 内存利用率困难,Kubernetes 不提供对 Linux 系统上swap的支持;在1.22 版中,Linux swap 特性以 Alpha 版本引入,在 1.28 版中,对 Linux swap的支持已升级为 Beta 版) 本次安装中不启用该特性,所以禁用 swap。
Kubernetes 1.28:在 Linux 上使用交换内存的 Beta 支持- 为内核加载 ipvs 模块(将后续的 kube-proxy 组件由 iptables 切换为 ipvs)kubernetes - 基于 IPVS 的集群内部负载均衡
# 配置 hosts 解析
cat << 'EOF' | tee -a /etc/hosts
192.167.16.116 master1
192.167.16.117 node1
192.167.16.118 node2
EOF
# 安装依赖软件
softs=(wget git psmisc socat ntp nfs-utils telnet ipvsadm ipset sysstat conntrack libseccomp bash-completion)
for i in "${softs[@]}"
do
if yum install ${i} -y -q >/dev/null 2>&1;then
echo "安装 ${i} 完成"
else
echo "安装 ${i} 失败"
fi
done
# 关闭防火墙
if systemctl status iptables.service >/dev/null 2>&1 ;then
if systemctl disable iptables.service --now ;then
echo "关闭 iptables 完成"
else
echo "关闭 iptables 失败"
fi
fi
if systemctl status firewalld.service >/dev/null 2>&1 ;then
if systemctl disable firewalld.service --now ;then
echo "关闭 firewalld 完成"
else
echo "关闭 firewalld 失败"
fi
fi
# 关闭 selinux
selinux_status=$(getenforce)
if [[ $selinux_status != 'disable' ]] ;then
if setenforce 0 ;then
echo "临时关闭 selinux 完成"
else
echo "临时关闭 selinux 失败"
fi
if sed -ri '/^[^#]*SELINUX=/s#=.+$#=disabled#' /etc/selinux/config ;then
echo "设置 /etc/selinux/config,永久关闭 selinux 完成"
else
echo "设置 /etc/selinux/config,永久关闭 selinux 失败"
fi
fi
# 关闭 swap
if swapoff -a && sysctl -w vm.swappiness=0 >/dev/null ;then
echo "临时关闭 swap 完成"
else
echo "临时关闭 swap 失败"
fi
if sed -ri '/^[^#]*swap/s@^@#@' /etc/fstab ;then
echo "设置 /etc/fstab,永久关闭 swap 完成"
else
echo "设置 /etc/fstab,永久关闭 swap 失败"
fi
# 调整内核参数
module=(ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter)
rm -rf /etc/modules-load.d/ipvs.conf
for i in "${module[@]}"
do
/sbin/modinfo -F filename $i |& grep -qv ERROR && echo $i >> /etc/modules-load.d/ipvs.conf || :
done
if systemctl enable --now systemd-modules-load.service && systemctl restart systemd-modules-load.service ;then
echo "设置 ipvs 内核模块完成"
else
echo "设置 ipvs 内核模块失败"
fi
3.2. 在 master 节点安装 docker,cri-docker
# 安装 docker
yum install -y docker-ce-24.0.9-1.el9 -y
# 启动 docker 并设置开机自启
systemctl enable --now docker
# 下载 cri-docker
cd /root
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.20/cri-dockerd-0.3.20.amd64.tgz
# 解压
tar -zxf cri-dockerd-0.3.20.amd64.tgz
# 安装
mv cri-dockerd/cri-dockerd /usr/local/bin/
# 配置 service 文件
cat << 'EOF' | tee /usr/lib/systemd/system/cri-docker.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd://
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
# 配置 socket 文件
cat << 'EOF' | tee /usr/lib/systemd/system/cri-docker.socket
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
EOF
# 启动 cri-docker 并设置开机自启
systemctl enable --now cri-docker
3.3. 在 master 节点安装 kubeadm,kubelet,kubectl
通过 yum 安装 kubeadm,kubelet 和 kubectl 时,同步安装了 cri-tools 和 kubernetes-cni 插件,如果使用的是二进制安装,需要在同步完成 cri-tools 和 kubernetes-cni 插件的安装。
yum install -y kubeadm-1.32.5-150500.1.1 kubectl-1.32.5-150500.1.1 kubelet-1.32.5-150500.1.1 -y
3.4. 在 master 节点上使用 kubeadm 列出所需的基础镜像,准备离线镜像进行导入
# 列出所需镜像
kubeadm config images list
# 导入准备好的镜像,镜像需要与上述列出的版本一致
cd /root/
tar -zxf kubernetes-1.32.5-images.tar.gz
cd kubernetes-1.32.5
for i in $(ls); do docker load -i ${i}; done
3.5. 在 master 节点上使用 kubeadm 初始化集群
使用 kubeadm 进行集群初始化或集群扩展时,可以使用配置文件的方式注入配置,通过配置文件可以将配置持久化存储下来,在之后使用集群时可以快速确定创建的配置。
mkdir -p /root/kubeadm
# 创建集群初始化配置文件
cat << 'EOF' | tee /root/kubeadm/init.yaml
# kubeadm 初始化集群的配置信息
apiVersion: kubeadm.k8s.io/v1beta4
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
# 调整 apiserver 的地址为实际的 ip
advertiseAddress: 192.167.16.113
bindPort: 6443
nodeRegistration:
# 节点 cri 节点调整为 cri-docker ,因为 master 部署的是 docker,目前通过 cri-docker 接入
criSocket: unix:///var/run/cri-dockerd.sock
imagePullPolicy: IfNotPresent
imagePullSerial: true
name: node
taints: null
timeouts:
controlPlaneComponentHealthCheck: 4m0s
discovery: 5m0s
etcdAPICall: 2m0s
kubeletHealthCheck: 4m0s
kubernetesAPICall: 1m0s
tlsBootstrap: 5m0s
upgradeManifests: 5m0s
---
# 集群配置信息
apiServer: {}
apiVersion: kubeadm.k8s.io/v1beta4
# 配置证书有效期及路径信息
caCertificateValidityPeriod: 87600h0m0s
certificateValidityPeriod: 8760h0m0s
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns: {}
encryptionAlgorithm: RSA-2048
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: registry.k8s.io
kind: ClusterConfiguration
kubernetesVersion: 1.32.5
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16
proxy: {}
scheduler: {}
---
# 配置 kube-proxy 设置运行模式为 ipvs
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
mode: "ipvs"
EOF
执行集群初始化
# 先启动 kubelet
systemctl enable --now kubelet
# 先运行 dry-run 看看是否存在报错
kubeadm init --config init.yaml --dry-run
# 无报错后,再执行初始化
kubeadm init --config init.yaml
# 安装后,配置 kubectl
mkdir -p /root/.kube
cp -i /etc/kubernetes/admin.conf /root/.kube/config
# 此时可以执行 kubectl 查看 master 节点信息(网络插件未安装,此时节点状态为 NotReady)
kubectl get node
3.6. 在 node1 节点,安装 docker、cri-docker,安装 kubeadm、kubelet,导入镜像
# 安装 docker
yum install -y docker-ce-24.0.9-1.el9 -y
# 启动 docker 并设置开机自启
systemctl enable --now docker
# 下载 cri-docker
cd /root/
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.20/cri-dockerd-0.3.20.amd64.tgz
# 解压
tar -zxf cri-dockerd-0.3.20.amd64.tgz
# 安装
mv cri-dockerd/cri-dockerd /usr/local/bin/
# 配置 service 文件
cat << 'EOF' | tee /usr/lib/systemd/system/cri-docker.service
[Unit]
Description=CRI Interface for Docker Application Container Engine
Documentation=https://docs.mirantis.com
After=network-online.target firewalld.service docker.service
Wants=network-online.target
Requires=cri-docker.socket
[Service]
Type=notify
ExecStart=/usr/local/bin/cri-dockerd --container-runtime-endpoint fd://
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
# Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.
# Both the old, and new location are accepted by systemd 229 and up, so using the old location
# to make them work for either version of systemd.
StartLimitBurst=3
# Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.
# Both the old, and new name are accepted by systemd 230 and up, so using the old name to make
# this option work for either version of systemd.
StartLimitInterval=60s
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Comment TasksMax if your systemd version does not support it.
# Only systemd 226 and above support this option.
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
EOF
# 配置 socket 文件
cat << 'EOF' | tee /usr/lib/systemd/system/cri-docker.socket
[Unit]
Description=CRI Docker Socket for the API
PartOf=cri-docker.service
[Socket]
ListenStream=%t/cri-dockerd.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
EOF
# 启动 cri-docker 并设置开机自启
systemctl enable --now cri-docker
# 安装 kubeadm,kubelet
yum install -y kubeadm-1.32.5-150500.1.1 kubelet-1.32.5-150500.1.1 -y
systemctl enable --now kubelet
# 导入准备好的镜像,镜像需要与上述列出的版本一致
cd /root/
tar -zxf kubernetes-1.32.5-images.tar.gz
cd kubernetes-1.32.5
for i in $(ls); do docker load -i ${i}; done
3.7. 在 node1 节点使用 kubeadm 加入集群
在 master 节点上获取 启动引导令牌
# 查看是否够存在 启动令牌引导
kubectl get secret -n kube-system | grep bootstrap-token
# 如果不存在令牌,则通过 kubeadm 创建
kubeadm token create --print-join-command
# 如果存在令牌,则获取 token
echo "$(kubectl get secrets -n kube-system $(kubectl get secret -n kube-system | grep bootstrap-token|awk '{print $1}') -o yaml | grep token-id | awk -F': ' '{print $2}'|base64 -d).$(kubectl get secrets -n kube-system $(kubectl get secret -n kube-system | grep bootstrap-token|awk '{print $1}') -o yaml | grep token-secret | awk -F': ' '{print $2}'|base64 -d)"
在 node1 节点上创建 join.yaml 文件
mkdir -p /root/kubeadm
cat << 'EOF' | tee /root/kubeadm/join.yaml
apiVersion: kubeadm.k8s.io/v1beta4
caCertPath: /etc/kubernetes/pki/ca.crt
discovery:
bootstrapToken:
apiServerEndpoint: 192.167.16.116:6443
# 获取的 token
token: abcdef.0123456789abcdef
unsafeSkipCAVerification: true
timeout: 5m0s
# 获取的 token
tlsBootstrapToken: abcdef.0123456789abcdef
kind: JoinConfiguration
nodeRegistration:
criSocket: unix:///var/run/cri-dockerd.sock
imagePullPolicy: IfNotPresent
taints: null
name: node1
EOF
将节点 node1 加入集群中
kubeadm join --config join.yaml
3.8. 在 node2 节点安装 containerd,安装 kubeadm、kubelet,导入镜像
# 安装 containerd
yum install -y containerd.io-1.7.22-3.1.el9 -y
# 生成 containerd 默认配置
containerd config default | tee /etc/containerd/config.toml
# 修改 containerd 的 Cgroup 控制器为 Systemd 设置
sed -i "s/SystemdCgroup = false/SystemdCgroup = true/g" config.toml
# 修改 containerd 的默认 pause 版本为 3.10
sed -i 's/3.8/3.10/g' config.toml
# 启动 containerd 并设置开机自启
systemctl enable --now containerd
# 安装 kubeadm,kubelet
yum install -y kubeadm-1.32.5-150500.1.1 kubelet-1.32.5-150500.1.1 -y
systemctl enable --now kubelet
# 导入准备好的镜像,镜像需要与上述列出的版本一致
cd /root/
tar -zxf kubernetes-1.32.5-images.tar.gz
cd kubernetes-1.32.5
# 注意 contianerd 的镜像资源区分空间,需要导入的 kubernetes 的空间 k8s.io 中
for i in $(ls); do ctr -n k8s.io i import ${i}; done
3.10. 在 node2 节点使用 kubeadm 加入集群
在 master 节点上获取 启动引导令牌
# 查看是否够存在 启动令牌引导
kubectl get secret -n kube-system | grep bootstrap-token
# 如果不存在令牌,则通过 kubeadm 创建
kubeadm token create --print-join-command
# 如果存在令牌,则获取 token
echo "$(kubectl get secrets -n kube-system $(kubectl get secret -n kube-system | grep bootstrap-token|awk '{print $1}') -o yaml | grep token-id | awk -F': ' '{print $2}'|base64 -d).$(kubectl get secrets -n kube-system $(kubectl get secret -n kube-system | grep bootstrap-token|awk '{print $1}') -o yaml | grep token-secret | awk -F': ' '{print $2}'|base64 -d)"
在 node2 节点上创建 join.yaml 文件
mkdir -p /root/kubeadm
cat << 'EOF' | tee /root/kubeadm/join.yaml
apiVersion: kubeadm.k8s.io/v1beta4
caCertPath: /etc/kubernetes/pki/ca.crt
discovery:
bootstrapToken:
apiServerEndpoint: 192.167.16.116:6443
# 获取的 token
token: abcdef.0123456789abcdef
unsafeSkipCAVerification: true
timeout: 5m0s
# 获取的 token
tlsBootstrapToken: abcdef.0123456789abcdef
kind: JoinConfiguration
nodeRegistration:
# 一定需要注意修改 contianerd 的 criSocket 句柄
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
taints: null
name: node2
EOF
将节点 node2 加入集群中
cd /root/kubeadm && kubeadm join --config join.yaml
3.11. 部署网络插件
集群中加入 node1 和 node2 后,因为集群网络尚未就绪,所以节点都处于 NotReady 状态:
此时需要部署网络插件,让集群网络状态就绪。
手工导入 flannel 镜像
# mster、node1 和 node2 导入 flannel 镜像
cd /root/
tar -zxf flannel.tar.gz
cd /root/flannel
# master 和 node1 使用 docker 导入镜像
for i in $(ls *.tar); do docker load -i ${i}; done
# node2 使用 containerd 导入镜像
for i in $(ls *.tar); do ctr -n k8s.io i import ${i}; done
在 master 上部署flannel 服务
cd /root/flannel
kubectl apply -f kube-flannel.yml
待网络插件就绪后,节点进入 Ready 状态,此时集群部署完毕。
更多推荐
所有评论(0)