碎碎念
- 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 证书
876600h
转换后是一百年
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
创建 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