基于 cri-dockerd 二进制部署 k8s-v1.26
kubernetes 已经在 1.24 版本中删除了 docker-shim 这个组件,使得 docker 无法对接 1.24 以后版本的kubernetes PS:之前都是 kubernetes 团队维护 docker-shim 组件,因为一些历史原因,放弃了docker-shim 之前写过一篇 基于 containerd 二进制部署 k8s-v1.23.3,总体体验下来,觉得自己被。
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
- kubernetes 已经在 1.24 版本中删除了 docker-shim 这个组件,使得 docker 无法对接 1.24 以后版本的
kubernetes PS:之前都是 kubernetes 团队维护 docker-shim 组件,因为一些历史原因,放弃了
docker-shim 之前写过一篇 基于 containerd 二进制部署 k8s-v1.23.3,总体体验下来,觉得自己被
docker 惯坏了 containerd 的上手很不习惯,原生的 ctr 命令不好用,build 镜像也依赖 buildkit 服务
对于菜鸡的我来说,containerd 就好比手动挡的车,只有老司机才能驾驭,我更喜欢自动挡多一点
这篇文章,都是使用了当前最新版本的组件来部署,仅供学习使用
实际的生产也好,公司环境也好,还是要选择当前的稳定版本,直接使用最新版会过于激进
另外,如果有需求部署 kubernetes 的话,在不喜欢 containerd 的前提下,可以直接使用 cri-dockerd ,这样在后期如果需要提升到 1.24 以上版本的 kubernetes 就可以减少很多烦心事
虽然,不管是升级容器运行时版本还是升级 kubernetes 版本,都会很糟心,只不过,能少一个是一个 [手动狗头.jpg]
提示:以下是本篇文章正文内容,下面案例可供参考
kubernetes | v1.26.3 |
---|---|
etcd | v3.5.7 |
cfssl | v1.6.3 |
– | – |
docker | 23.0.1 |
cri-dockerd | v0.3.1 |
cni | v1.1.1 |
calico | v3.25.0 |
大部分的组件都是通过 github 下载的,下面整合了下载链接,可以开始前先准备好二进制文件
# kubernetes 二进制文件
https://dl.k8s.io/v1.26.3/kubernetes-server-linux-amd64.tar.gz
# etcd 二进制文件
https://github.com/etcd-io/etcd/releases/download/v3.5.7/etcd-v3.5.7-linux-amd64.tar.gz
# cfssl 二进制文件
https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssl_1.6.3_linux_amd64
# cfssljson 二进制文件
https://github.com/cloudflare/cfssl/releases/download/v1.6.3/cfssljson_1.6.3_linux_amd64
# docker 二进制文件
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/static/stable/x86_64/docker-23.0.1.tgz
# cri-dockerd 二进制文件
https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.1/cri-dockerd-0.3.1.amd64.tgz
IP | 角色 |
---|---|
192.168.11.147 | master/worker |
192.168.11.148 | master/worker |
192.168.11.149 | master/worker |
一般情况下,master 节点也会复用成 worker 节点,毕竟机器也挺贵的 如果有特殊要求,不希望 master
节点运行容器的话,这里需要注意一些场景 metrics-server 服务获取节点资源使用情况时,需要保证和 apiserver之间的网络可以互通
如果 master 节点不部署容器,理论上只需要部署网络插件来互通网络,实际上我没有尝试过,因为我穷,我都是 master 节点复用 worker 节点
我只尝试过 master 节点复用 worker 节点,但是 master节点不调度容器的场景,因为我的网络插件都是以容器的方式运行的
开始整活
挑选一个节点作为操作节点,我这边就按照顺序,选择了 192.168.11.147 这个节点来进行后面的操作
环境准备
创建干活的目录
这个目录,主要是建立一些模板文件,然后直接通过分发和 ssh 的方式来部署,减少频繁切换节点的操作 这里利用了 shell
变量的方式来操作的,如果终端退出过,需要重新定义 work_dir 这个变量,否则后面的其他操作会导致目录不存在的报错
work_dir='/data/k8s-work-dir'
mkdir -p ${work_dir}/{bin,images,pkg,tmp/{ssl,service}}
节点免密操作
静默生成 ssh 证书
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -q
分发 ssh 证书到所有节点,包含操作节点本身,下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do ssh-copy-id ${ip_head}.${i};done
关闭防火墙
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
ssh ${ip_head}.${i} "systemctl disable firewalld"; \
ssh ${ip_head}.${i} "systemctl stop firewalld"; \
done
关闭 selinux
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
ssh ${ip_head}.${i} "setenforce 0"; \
ssh ${ip_head}.${i} "sed -i 's/SELINUX=[a-z].*/SELINUX=disabled/g' /etc/selinux/config"; \
done
有返回 setenforce: SELinux is disabled 这样的内容,说明 selinux
已经被关闭过了,不需要理会,继续往下操作
关闭 swap 分区
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
ssh ${ip_head}.${i} "swapoff -a"; \
ssh ${ip_head}.${i} "sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab"; \
done
开启内核模块
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
ssh ${ip_head}.${i} "modprobe ip_vs"; \
ssh ${ip_head}.${i} "modprobe ip_vs_rr"; \
ssh ${ip_head}.${i} "modprobe ip_vs_wrr"; \
ssh ${ip_head}.${i} "modprobe ip_vs_sh"; \
ssh ${ip_head}.${i} "modprobe nf_conntrack"; \
ssh ${ip_head}.${i} "modprobe nf_conntrack_ipv4"; \
ssh ${ip_head}.${i} "modprobe br_netfilter"; \
ssh ${ip_head}.${i} "modprobe overlay"; \
done
避免服务器宕机重启后没有开启上面的内核模块,使用下面的方法来保证重启后会自动加载内核模块
cat << EOF > ${work_dir}/tmp/service/k8s-modules.conf
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
nf_conntrack_ipv4
br_netfilter
overlay
EOF
分发文件并启动内核模块加载服务 下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
scp ${work_dir}/tmp/service/k8s-modules.conf ${ip_head}.${i}:/etc/modules-load.d/; \
ssh ${ip_head}.${i} "systemctl enable systemd-modules-load"; \
ssh ${ip_head}.${i} "systemctl restart systemd-modules-load"; \
ssh ${ip_head}.${i} "systemctl is-active systemd-modules-load"; \
done
返回active表示自动加载模块服务启动成功
配置内核参数
以下的参数适用于 3.x 和 4.x 系列的内核
cat << EOF > ${work_dir}/tmp/service/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
# 关闭tcp_tw_recycle,否则和NAT冲突,会导致服务不通
net.ipv4.tcp_tw_recycle=0
# 不允许将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
分发文件并加载内核参数
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
scp ${work_dir}/tmp/service/kubernetes.conf ${ip_head}.${i}:/etc/sysctl.d/; \
ssh ${ip_head}.${i} "sysctl -p /etc/sysctl.d/kubernetes.conf"; \
done
清空 iptables 规则
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
ssh ${ip_head}.${i} "iptables -F && iptables -X && iptables -F -t nat && iptables -X -t nat"; \
ssh ${ip_head}.${i} "iptables -P FORWARD ACCEPT"; \
done
配置 ca 证书
cat << EOF > ${work_dir}/tmp/ssl/ca-config.json
{
"signing": {
"default": {
"expiry": "876600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876600h"
}
}
}
}
EOF
cat << EOF > ${work_dir}/tmp/ssl/ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "876600h"
}
}
EOF
准备 cfssl 工具
我提前下载好了 cfssl 工具,放在了 ${work_dir}/bin 目录下了,大家要注意自己放的路径
mv ${work_dir}/bin/cfssl_1.6.3_linux_amd64 ${work_dir}/bin/cfssl
mv ${work_dir}/bin/cfssljson_1.6.3_linux_amd64 ${work_dir}/bin/cfssljson
chmod +x ${work_dir}/bin/cfssl*
创建 ca 证书
不指定路径的情况下,生成的证书和查找的证书都是基于当前路径,如果有出现证书文件不存在,检查一下路径是否有添加以及路径是否正确
${work_dir}/bin/cfssl gencert -initca ${work_dir}/tmp/ssl/ca-csr.json | \
${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/ca
部署 master 组件
部署 etcd 组件
准备 etcd 二进制文件
我提前下载好了 etcd 二进制文件,放在了 ${work_dir}/bin 目录下了,大家要注意自己放的路径
cd ${work_dir}/bin && \ tar xf etcd-v3.5.7-linux-amd64.tar.gz
下面的 ip 记得替换成自己的节点 ip
需要部署 etcd 组件的节点 ip 都需要在证书文件内记录下来 注意 json 格式,最后一个 ip 后面不要有 , 逗号
配置 etcd 证书
cat << EOF > ${work_dir}/tmp/ssl/etcd-csr.json
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"192.168.11.147",
"192.168.11.148",
"192.168.11.149"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
创建 etcd 证书
${work_dir}/bin/cfssl gencert \
-ca=${work_dir}/tmp/ssl/ca.pem \
-ca-key=${work_dir}/tmp/ssl/ca-key.pem \
-config=${work_dir}/tmp/ssl/ca-config.json \
-profile=kubernetes ${work_dir}/tmp/ssl/etcd-csr.json | \
${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/etcd
配置 etcd 为 systemctl 管理
下面的 ip 记得替换成自己的节点 ip
etcd 参数
创建 systemctl 启动模板
注:下面的 \ 不要改成 \ ,这是因为会被 EOF 转义,所以要在前面加一个转义,这样生成的文件里面,每一行都会带有一个 \
cat << EOF > ${work_dir}/tmp/service/kube-etcd.service.template
[Unit]
Description=Etcd Server
After=network.target
After=network-online.target
Wants=network-online.target
Documentation=https://github.com/coreos
[Service]
Type=notify
WorkingDirectory=##etcdDataPath##
ExecStart=##etcdBin##/etcd \\
--wal-dir= \\
--data-dir=##etcdDataPath## \\
--name=etcd-##etcdHost## \\
--cert-file=##sslPath##/etcd.pem \\
--key-file=##sslPath##/etcd-key.pem \\
--peer-cert-file=##sslPath##/etcd.pem \\
--peer-key-file=##sslPath##/etcd-key.pem \\
--trusted-ca-file=##sslPath##/ca.pem \\
--peer-trusted-ca-file=##sslPath##/ca.pem \\
--initial-advertise-peer-urls=https://##etcdHost##:2380 \\
--listen-peer-urls=https://##etcdHost##:2380 \\
--listen-client-urls=https://##etcdHost##:2379,http://127.0.0.1:2379 \\
--advertise-client-urls=https://##etcdHost##:2379 \\
--initial-cluster-token=etcd-cluster-0 \\
--initial-cluster=##etcdNodes## \\
--initial-cluster-state=new \\
--snapshot-count=50000 \\
--auto-compaction-retention=1 \\
--auto-compaction-mode=periodic \\
--max-request-bytes=10485760 \\
--quota-backend-bytes=8589934592
Restart=always
RestartSec=15
LimitNOFILE=65536
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
生成各个 etcd 节点的 systemctl 启动文件
下面的 ip 记得替换成自己的节点 ip
etcdNodes 要改成所有 etcd 节点的 ip,注意最后一个 ip 后面没有 , 逗号
–initial-cluster 参数的格式为:<–name 参数>=https://<etcd 节点 ip>:2380 ,如果等于号前面的内容和 --name 参数 参数不一致,会导致 etcd 集群初始化失败 etcdBin 是 etcd 二进制文件的路径
etcdDataPath 是 etcd 数据存储路径 sslPath 是 etcd 证书存储路径
ip_head='192.168.11';for i in 147 148 149;do \
etcdHost="${ip_head}.${i}"; \
etcdNodes="etcd-192.168.11.147=https://192.168.11.147:2380,etcd-192.168.11.148=https://192.168.11.148:2380,etcd-192.168.11.149=https://192.168.11.149:2380"; \
etcdBin='/data/etcd-data/bin'; \
etcdDataPath='/data/etcd-data/data'; \
sslPath='/etc/kubernetest/ssl'; \
sed -e "s|##etcdHost##|${etcdHost}|g" -e "s|##etcdBin##|${etcdBin}|g" -e "s|##etcdDataPath##|${etcdDataPath}|g" -e "s|##sslPath##|${sslPath}|g" -e "s|##etcdNodes##|${etcdNodes}|g" ${work_dir}/tmp/service/kube-etcd.service.template > ${work_dir}/tmp/service/kube-etcd.service.${etcdHost}; \
done
文件并启动 etcd 集群
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
etcdHost="${ip_head}.${i}"; \
ssh ${etcdHost} "mkdir -p ${etcdBin} ${sslPath}"; \
ssh ${etcdHost} "mkdir -p ${etcdDataPath} -m 700"; \
scp ${work_dir}/tmp/ssl/{ca*.pem,etcd*.pem} ${etcdHost}:${sslPath}/; \
scp ${work_dir}/tmp/service/kube-etcd.service.${etcdHost} ${etcdHost}:/usr/lib/systemd/system/kube-etcd.service; \
scp ${work_dir}/bin/etcd-v3.5.7-linux-amd64/{etcd,etcdctl} ${etcdHost}:${etcdBin}/; \
ssh ${etcdHost} "systemctl enable kube-etcd && systemctl start kube-etcd --no-block"; \
done
验证 etcd 集群
下面的 ip 记得替换成自己的节点 ip
ip_head='192.168.11';for i in 147 148 149;do \
etcdHost="${ip_head}.${i}"; \
ssh ${etcdHost} "ETCDCTL_API=3 ${etcdBin}/etcdctl \
--endpoints=https://${etcdHost}:2379 \
--cacert=${sslPath}/ca.pem \
--cert=${sslPath}/etcd.pem \
--key=${sslPath}/etcd-key.pem \
endpoint health"; \
done
预期返回类似如下的回显,ip 显示的是大家自己机器的 ip,只要看到 is healthy: successfully 说明节点是正常的
https://192.168.11.147:2379 is healthy: successfully committed proposal: took = 6.156014ms
https://192.168.11.148:2379 is healthy: successfully committed proposal: took = 7.048715ms
https://192.168.11.149:2379 is healthy: successfully committed proposal: took = 19.618844ms
部署 apiserver 组件
准备 apiserver 二进制文件
我提前下载好了 apiserver 二进制文件,放在了 ${work_dir}/bin 目录下了,大家要注意自己放的路径
cd ${work_dir}/bin/ && \
tar xf kubernetes-server-linux-amd64.tar.gz
这里分享一个小技巧,解压出来的 kubernetes 二进制文件里面包含了 kubeadm,使用 kubeadm 命令可以看到当前版本的
kubernetes 的镜像版本,包含了 etcd ,pause 和 coredns
${work_dir}/bin/kubernetes/server/bin/kubeadm config images list
可以看到,官方配套的组件版本如下:
registry.k8s.io/kube-apiserver:v1.26.3
registry.k8s.io/kube-controller-manager:v1.26.3
registry.k8s.io/kube-scheduler:v1.26.3
registry.k8s.io/kube-proxy:v1.26.3
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.6-0
registry.k8s.io/coredns/coredns:v1.9.3
配置 apiserver 证书
下面的 ip 记得替换成自己的节点 ip
和 etcd 组件一样,把所有的 apiserver 节点 ip 都要写进去 如果有 SLB 等高可用 ip,也要写进去
(我这里没有做高可用,就不写了)
10.88.0.1 是 k8s 的服务 ip,千万不要和现有的网络一致,避免出现冲突 这个大家根据自己的实际场景来决定是否修改,如果有修改的,后面涉及到的 ip 都要记得修改 同样的,在配置 ip 的时候,注意 json
格式的 , 逗号位置
cat << EOF > ${work_dir}/tmp/ssl/apiserver-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"192.168.11.147",
"192.168.11.148",
"192.168.11.149",
"10.88.0.1",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
创建 apiserver 证书
${work_dir}/bin/cfssl gencert \
-ca=${work_dir}/tmp/ssl/ca.pem \
-ca-key=${work_dir}/tmp/ssl/ca-key.pem \
-config=${work_dir}/tmp/ssl/ca-config.json \
-profile=kubernetes ${work_dir}/tmp/ssl/apiserver-csr.json | \
${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/apiserver
配置 metrics-server 证书
这个看各自的需求是否要部署 metrics-server 服务 没有 metrics-server 只是影响 dashboard
的图形化不展示 没有 metrics-server 就玩不了 kubernetes 的 hpa 功能
cat << EOF > ${work_dir}/tmp/ssl/aggregator-csr.json
{
"CN": "aggregator",
"hosts": [
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "ShangHai",
"L": "ShangHai",
"O": "k8s",
"OU": "System"
}
]
}
EOF
创建 metrics-server 证书
${work_dir}/bin/cfssl gencert \
-ca=${work_dir}/tmp/ssl/ca.pem \
-ca-key=${work_dir}/tmp/ssl/ca-key.pem \
-config=${work_dir}/tmp/ssl/ca-config.json \
-profile=kubernetes ${work_dir}/tmp/ssl/aggregator-csr.json | \
${work_dir}/bin/cfssljson -bare ${work_dir}/tmp/ssl/aggregator
配置 apiserver 为 systemctl 管理
下面的 ip 记得替换成自己的节点 ip
–service-cluster-ip-range 参数的 ip 网段要和 apiserver-csr.json 里面的 10.88.0.1 是一个网段的
–etcd-servers 写上所有的 etcd 节点 如果不考虑部署 metrics-server 服务,以下七个参数需要去掉
–requestheader-client-ca-file
–requestheader-allowed-names
–requestheader-extra-headers-prefix
–requestheader-group-headers
–requestheader-username-headers
–proxy-client-cert-file
–proxy-client-key-file apiserver 参数创建 systemctl 启动模板
cat << EOF > ${work_dir}/tmp/service/kube-apiserver.service.template
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=network.target
[Service]
ExecStart=##k8sBin##/kube-apiserver \\
--secure-port=6443 \\
--allow-privileged=true \\
--anonymous-auth=false \\
--api-audiences=api,istio-ca \\
--authorization-mode=Node,RBAC \\
--bind-address=##k8sHost## \\
--client-ca-file=##sslPath##/ca.pem \\
--endpoint-reconciler-type=lease \\
--etcd-cafile=##sslPath##/ca.pem \\
--etcd-certfile=##sslPath##/apiserver.pem \\
--etcd-keyfile=##sslPath##/apiserver-key.pem \\
--etcd-servers=##etcdEndpoints## \\
--kubelet-certificate-authority=##sslPath##/ca.pem \\
--kubelet-client-certificate=##sslPath##/apiserver.pem \\
--kubelet-client-key=##sslPath##/apiserver-key.pem \\
--service-account-issuer=https://kubernetes.default.svc \\
--service-account-signing-key-file=##sslPath##/ca-key.pem \\
--service-account-key-file=##sslPath##/ca.pem \\
--service-cluster-ip-range=10.88.0.0/16 \\
--service-node-port-range=30000-32767 \\
--tls-cert-file=##sslPath##/apiserver.pem \\
--tls-private-key-file=##sslPath##/apiserver-key.pem \\
--requestheader-client-ca-file=##sslPath##/ca.pem \\
--requestheader-allowed-names= \\
--requestheader-extra-headers-prefix=X-Remote-Extra- \\
--requestheader-group-headers=X-Remote-Group \\
--requestheader-username-headers=X-Remote-User \\
--proxy-client-cert-file=##sslPath##/aggregator.pem \\
--proxy-client-key-file=##sslPath##/aggregator-key.pem \\
--enable-aggregator-routing=true \\
--v=2
Restart=always
RestartSec=5
Type=notify
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
EOF
完成
更多推荐
所有评论(0)