废话篇
这篇文章什么时候写的
北京时间:
2024年9月
为什么是 openeuler
centos 7
已经于2024 年 06 月 30 日停止维护
,国内又信创热潮,对于后期来说,谁也不知道形势会发生什么样的变化
- 目前国产操作系统有:
openeuler(华为欧拉)
,anolis OS(阿里龙蜥)
,OpenCloudOS(腾讯)
,UOS(统信)
,kylin OS(银河麒麟/商业版的,开源版是 openkylin)
- 至于为什么选择了
openeuler
,因为目前为止,只有openeuler
不仅有 iso 镜像,还有wsl
,docker 镜像
,甚至还支持公有云镜像,现在国内都没法直接访问 dockerhub 了,谁也不知道以后是不是连 docker 的基础镜像也会有干预,先提前有个准备
为什么是 22.03 lts sp4
因为
22.03 lts sp4
是2024年6月份
的最新版本,生命周期也是持续到 2026 年的
高可用架构
- 如果是公有云服务器,可以直接买公有云的 lb 服务就好了,简单粗暴有人抓
- 如果是本地私有化,我这边使用的是 keepalived+nginx(stream 4层负载) 的架构来实现 apiserver 的高可用
本次实验是以容器的形式来部署 nginx 和 keepalived,主要目的是为了减少不同环境差异导致部署方式不同
- 下面的丑图来解释一下 ha 的场景
- keepalived 使用 backup 的模式部署
- VIP 所在机器的 keepalived 对当前节点的 nginx 做健康检测,通过对应端口负载到背后的 apiserver 服务
- 使用 nginx 的 steam 是为了节省机器的资源开支,用 upstream 属于七层负载,相较而言,资源使用会更高
题外话
当时本来想用静态 pod 的方式来运行 nginx 和 keepalived,后来发现,静态 pod 不支持 API 对象,只能放弃了,具体的查看
创建静态 Pod
- 下面的这个部署方式,也就适合测试环境使用,生产环境,不建议把高可用组件放到同一个 k8s 集群里面,最好是外面独立部署,包括 etcd 也可以考虑外置
干活篇
环境介绍
组件 | 版本 |
---|---|
OS | openEuler 22.03 (LTS-SP4) |
containerd | 1.6.33 |
k8s | 1.28.2-0 |
nerdctl | 1.7.6 |
nginx | 1.26.0 |
keepalived | 2.3.1 |
机器 ip 和对应的服务
IP | HOSTNAME | SERVICE/ROLE |
---|---|---|
192.168.22.111 | manager-k8s-cluster-01 | k8s-master+k8s-worker+keepalived+nginx |
192.168.22.112 | manager-k8s-cluster-02 | k8s-master+k8s-worker+keepalived+nginx |
192.168.22.113 | manager-k8s-cluster-03 | k8s-master+k8s-worker+keepalived+nginx |
192.168.22.114 | manager-k8s-cluster-04 | k8s-worker |
192.168.22.115 | manager-k8s-cluster-05 | k8s-worker |
192.168.22.200 | / | VIP |
系统初始化相关
- 如果是虚拟机还没就绪,可以先启动一台机器,执行完初始化后,直接克隆机器更方便快捷
- 如果机器已经就绪了,下面的初始化操作,每个机器都需要执行
- 下面的操作省略了
静态 ip
和时间同步
的操作,大家自己操作一下
关闭防火墙
systemctl disable firewalld --now
关闭 selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
关闭 swap
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
开启内核模块
# 针对于 kubeproxy 使用 ipvs 模式的
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# 常规要开启的
modprobe nf_conntrack
modprobe br_netfilter
modprobe overlay
开启模块自动加载服务
cat > /etc/modules-load.d/k8s-modules.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
overlay
EOF
设置为开机自启
systemctl enable systemd-modules-load --now
sysctl 内核参数调整
cat <<EOF > /etc/sysctl.d/kubernetes.conf
# 开启数据包转发功能(实现vxlan)
net.ipv4.ip_forward=1
# iptables对bridge的数据进行处理
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-arptables=1
# 不允许将TIME-WAIT sockets重新用于新的TCP连接
net.ipv4.tcp_tw_reuse=0
# socket监听(listen)的backlog上限
net.core.somaxconn=32768
# 最大跟踪连接数,默认 nf_conntrack_buckets * 4
net.netfilter.nf_conntrack_max=1000000
# 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.swappiness=0
# 计算当前的内存映射文件数。
vm.max_map_count=655360
# 内核可分配的最大文件数
fs.file-max=6553600
# 持久连接
net.ipv4.tcp_keepalive_time=600
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=10
EOF
立即生效
sysctl -p /etc/sysctl.d/kubernetes.conf
20250117 更新
特殊操作:
/etc/sysctl.conf
文件里面的net.ipv4.ip_forward=0
会覆盖掉上面子配置文件里面的值
- 猜测是因为
/etc/openEuler_security/security.conf
文件里面配置了301@m@/etc/sysctl.conf@net.ipv4.ip_forward=@0
,但是不确定修改后会影响哪些,还是打算直接修改/etc/sysctl.conf
,这样就不会导致机器重启,kubelet 起不来的情况
sed -i 's|^net.ipv4.ip_forward.*|net.ipv4.ip_forward=1|g' /etc/sysctl.conf
sysctl -p
清空 iptables 规则
iptables -F && \
iptables -X && \
iptables -F -t nat && \
iptables -X -t nat && \
iptables -P FORWARD ACCEPT
安装各种依赖和工具
yum install -y vim wget tar net-tools jq bash-completion tree bind-utils telnet unzip nc
修改 .bashrc 文件
具体参考我之前的博客:关于 openeuler 22.03-LTS-SP4 scp 失败问题的记录,主要影响的是 scp 命令,具体的,看大家自己选择
安装 kubeadm 和 kubelet
k8s 官方也没有 openeuler 的源,但是可以直接使用
kubernetes-el7
的源来安装,下面是配置kubernetes-el7
源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
安装 kubeadm 的时候,会自动安装 kubelet 和 kubectl 以及一些依赖的组件
yum install -y kubeadm-1.28.2-0
验证版本
kubeadm version
正常返回下面的内容,说明没问题
kubeadm version: &version.Info{Major:"1", Minor:"28", GitVersion:"v1.28.2", GitCommit:"89a4ea3e1e4ddd7f7572286090359983e0387b2f", GitTreeState:"clean", BuildDate:"2023-09-13T09:34:32Z", GoVersion:"go1.20.8", Compiler:"gc", Platform:"linux/amd64"}
简化 kubectl 命令
有时候实在懒得敲 kubectl 了,只想敲一个 k
ln -s /usr/bin/kubectl /usr/bin/k
启动 kubelet
配置开机自启
systemctl enable kubelet --now
安装 containerd
openeuler 可以用 docker 的 centos 里面的 rpm 来安装,这一点,还是比较方便的
cat <<EOF> /etc/yum.repos.d/docker.repo
[docker-ce-centos]
name=Docker CE Stable centos
baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7.9/x86_64/stable
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/docker-ce/linux/centos/gpg
EOF
安装 containerd
yum install -y containerd.io-1.6.33
生成默认的配置文件
containerd config default > /etc/containerd/config.toml
别的配置大家可以根据实际情况修改,国内的话,有一个参数可以修改,也可以不修改
sandbox_image
这个参数要指定pause
镜像,默认的是registry.k8s.io/pause:3.6
,可以自己提前准备好镜像,然后修改成这个 tag,也可以和我一样,替换成国内阿里的SystemdCgroup = false
这个参数需要修改,因为后面的 kubelet 也是用 systemd 这个 cgroup,默认导出的配置是 false,不配置会有下面的报错
openat2 /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf2248c8a5ab6855d0410a9f38c37b4a0.slice/cpuset.mems: no such file or directory
sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9"
SystemdCgroup = true
启动
containerd
,加入开机自启
systemctl enable containerd --now
配置
crictl
命令(安装 kubeadm 的时候,默认把 crictl 命令作为依赖下载了,需要通过配置文件,让crictl
命令读取containerd
的socket
文件来达到管理containerd
的目的)
crictl
命令默认的配置文件是/etc/crictl.yaml
,也可以自定义,使用crictl
命令的时候加上--config
来指定配置文件就可以了
echo 'runtime-endpoint: unix:///run/containerd/containerd.sock' > /etc/crictl.yaml
检查 crictl 和 containerd 的版本
crictl version
能展示下面的版本信息,说明部署和启动都没有问题了
Version: 0.1.0
RuntimeName: containerd
RuntimeVersion: 1.6.33
RuntimeApiVersion: v1
镜像准备
kubeadm 部署需要用到镜像,如果是内网环境,需要提前准备好镜像,然后导入镜像,用下面的命令可以查看需要提前准备哪些镜像
image-repository
就是后面 kubeadm 配置文件里面指定的,国内可以用下面的阿里云kubernetes-version
是指定 k8s 的版本
kubeadm config images list \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version 1.28.2
正常情况下,会输出下面这些内容
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.28.2
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.28.2
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.28.2
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.28.2
registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.9-0
registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.10.1
如果当前环境有网,网络可能不是很好,也可以提前用下面的命令先把镜像拉下来,这样不会在初始化阶段超时报错
kubeadm config images pull \
--image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
--kubernetes-version 1.28.2
拉取过程也会有下面这样的输出,到 coredns 说明镜像都拉取好了
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.28.2
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.28.2
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.28.2
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.28.2
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.9-0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.10.1
也可以提前把 calico 镜像准备好
ctr -n k8s.io image pull docker.io/calico/cni:v3.28.1
ctr -n k8s.io image pull docker.io/calico/node:v3.28.1
ctr -n k8s.io image pull docker.io/calico/kube-controllers:v3.28.1
初始化的操作,到这里就结束了
部署 master 组件
集群初始化
准备初始化的配置文件,相关的配置文件,可以从官方获取:Configuration APIs
# 集群相关的一些配置
## https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/
apiVersion: kubeadm.k8s.io/v1beta3
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
# apiserver 服务的 ip 地址和端口
advertiseAddress: 192.168.22.111
bindPort: 6443
nodeRegistration:
# 容器运行时的选择
criSocket: unix:///var/run/containerd/containerd.sock
imagePullPolicy: IfNotPresent
# k8s 的节点名称,也就是以后 kubectl get nodes 查看的名字
## 不指定的话,一般都是直接读取本机的 hostname
## 这里看个人习惯
name: 192.168.22.111
# 节点污点相关的,根据自己的情况配置
taints: null
---
apiServer:
# 高可用涉及到的 ip 地址属于额外的配置
## 需要在初始化的时候,加入到证书的 ip 清单里面
certSANs:
- 192.168.22.200
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta3
# k8s 相关证书的目录
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
# apiserver 的访问地址,先写当前节点的 ip
controlPlaneEndpoint: 192.168.22.111:6443
controllerManager: {
}
dns: {
}
etcd:
local:
# etcd 的数据持久化目录,尽量放 ssd 固态盘上面,etcd 比较在意磁盘 io
dataDir: /var/lib/etcd
# 镜像仓库地址,官方默认是 registry.k8s.io,咱们国内可以写阿里的
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: 1.28.2
networking:
# k8s dns 解析的域
dnsDomain: cluster.local
# k8s service 的网段
serviceSubnet: 10.96.0.0/12
# k8s pod 的网段
## 文章最后处会整理一下 ABC 三类地址的范围
podSubnet: 172.22.0.0/16
scheduler: {
}