kubernetes 集群搭建(kubeadm方式以containerd作为容器运行时)
kubernetes 集群搭建(kubeadm方式以containerd作为容器运行时)
0、 前置知识点
目前生产部署 Kubernetes 集群主要有两种方式:
1、kubeadm
Kubeadm 是一个 K8s 部署工具, 提供 kubeadm init 和 kubeadm join, 用于快速部 署 Kubernetes 集群。 官方地址: https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/
1.1、kubeadm 部署方式介绍
kubeadm 是官方社区推出的一个用于快速部署 kubernetes 集群的工具, 这个工具能通 过两条指令完成一个 kubernetes 集群的部署: 第一、 创建一个 Master 节点 kubeadm init 第二, 将 Node 节点加入到当前集群中 $ kubeadm join <Master 节点的 IP 和端口 >
2、二进制包
从 github 下载发行版的二进制包, 手动部署每个组件, 组成 Kubernetes 集群。 Kubeadm 降低部署门槛, 但屏蔽了很多细节, 遇到问题很难排查。 如果想更容易可 控, 推荐使用二进制包部署 Kubernetes 集群, 虽然手动部署麻烦点, 期间可以学习很 多工作原理, 也利于后期维护。
1、部署实验环境
1.0、主机规划
系统 | CPU | Mem | 主机数量 | 角色 |
---|---|---|---|---|
centos7.3 1611 | 2 | 4G(生产:8G+) | 1 | master |
centos7.3 1611 | 2 | 2G | 2 | node |
主机列表
主机角色 | 主机名 | 主机IP |
---|---|---|
MASTER | master | 192.168.245.100 |
NODE1 | node_1 | 192.168.245.101 |
NODE2 | node_2 | 192.168.245.102 |
- kubernetes:v1.23.1
- kubeadm:v1.23.1
1.1、主机名
[root@all ~]# hostnamectl set-hostname server_name
1.2、添加 hosts
[root@all ~]# cat >> /etc/hosts << EOF
192.168.23.106 k8s-master
192.168.23.107 k8s-node1
192.168.23.108 k8s-node2
EOF
1.3、关闭firewalld
[root@all ~]# systemctl stop firewalld
[root@all ~]# systemctl disable firewalld
[root@all ~]# firewall-cmd --state
1.4、关闭selinux
[root@all ~]# sed -i '/^SELINUX=/s/=.*/=disabled/' /etc/selinux/config
1.5、关闭swap
为每台主机关闭swap
#临时关闭
[root@all ~]# swapoff -a
#永久关闭:注释掉swap设置行
[root@all ~]# vim /etc/fstab
# /etc/fstab
# Created by anaconda on Wed Jul 24 10:32:24 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/centos-root / xfs defaults 0 0
UUID=146496df-1c2b-4822-9dab-1146e14f27d5 /boot xfs defaults 0 0
#/dev/mapper/centos-swap swap swap defaults 0 0
注释掉swap设置行,重启生效
1.6、安装iptables
[root@all ~]# yum -y install iptables-services
[root@all ~]# systemctl enable iptables
[root@all ~]# systemctl start iptables
[root@all ~]# iptables -nL
添加iptables规则
#清空规则
[root@all ~]# iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
#FORWARD设置为ACCEPT
[root@all ~]# iptables -P FORWARD ACCEPT
#保存设置
[root@all ~]# service iptables save
网桥过滤
#创建过滤规则
[root@all ~]# vim /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
vm.swappiness = 0
[root@all ~]# modprobe br_netfilter
[root@all ~]# lsmod | grep br_netfilter
[root@all ~]# sysctl -p /etc/sysctl.d/k8s.conf
将桥接的 IPv4 流量传递到 iptables 的链:
[root@all ~]# cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1
EOF
[root@all ~]# sysctl --system # 生效$
1.7、时间同步
[root@all ~]# ntpdate 1 time1.aliyun.com
2、部署容器运行时
2.0、K8S CRI介绍
K8S发布CRI(Container Runtime Interface),统一了容器运行时接口,凡是支持CRI的容器运行时,皆可作为K8S的底层容器运行时。
在Kubernetes 1.24,Dockershim组件正式从kubelet中移除。从Kubernetes 1.24开始,默认将无法使用Docker Engine作为容器运行。
K8S为什么要放弃使用Docker作为容器运行时,而使用containerd呢?
Dockershim组件一直以来,扮演着Docker、containerd 和CRI之间的翻译官角色,但事实上新版本的containerd 兼容CRI接口标准,可以绕开Docker直接与CRI对接,如果你使用Docker作为K8S容器运行时的话,kubelet需要先要通过dockershim去调用Docker,再通过Docker去调用containerd。如果你使用containerd作为K8S容器运行时的话,由于containerd内置了CRI插件,kubelet可以直接调用containerd。
使用containerd不仅性能提高了(调用链变短了),而且资源占用也会变小(Docker不是一个纯粹的容器运行时,具有大量其他功能)。
Docker Engine 没有实现 CRI, 而这是容器运行时在 Kubernetes 中工作所需要的。 为此,必须安装一个额外的服务 cri-dockerd。 cri-dockerd 是一个基于传统的内置 Docker 引擎支持的项目, 它在 1.24 版本从 kubelet 中移除。
你的容器运行时必须至少支持 v1alpha2 版本的容器运行时接口。
Kubernetes 1.26 默认使用 v1 版本的 CRI API。如果容器运行时不支持 v1 版本的 API, 则 kubelet 会回退到使用(已弃用的)v1alpha2 版本的 API
2.1、使用containerd作为K8S的容器运行时
本节概述了使用 containerd 作为 CRI 运行时的必要步骤。
使用以下命令在系统上安装 Containerd:
Step 1: 在[CentOS]使用dnf方法安装containerd.io
-
您可以[设置Docker的存储库](https://docs.docker.com/engine/install/centos/#install-使用存储库)并从中安装,以便于安装和升级任务。这是推荐的方法。
-
您可以下载RPM软件包并[手动安装](https://docs.docker.com/engine/install/centos/#install-来自软件包),并完全手动管理升级。这在一些情况下很有用,比如在没有互联网接入的气隙系统上安装Docker。
Step 2.1.1: 卸载旧版本的Docker
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
Step 2.1.2: 设置docker yum源
$ sudo yum install -y yum-utils
$ sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
Step 2.1.3: 安装 containerd.io
$ sudo yum install containerd.io
$ sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Step 2: 安装CNI 插件
下载安装包: cni-plugins-<OS>-<ARCH>-<VERSION>.tgz
下载链接: https://github.com/containernetworking/plugins/releases , 并在“/opt/cni/bin”下解压它:
$ mkdir -p /opt/cni/bin
$ wget https://github.com/containernetworking/plugins/releases/cni-plugins-<OS>-<ARCH>-<VERSION>.tgz
$ tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.1.1.tgz
使用源码包安装等更多方法请参考:容器运行时containerd的部署和使用
创建有效的配置文件 config.toml
后返回此步骤。
你可以在路径 /etc/containerd/config.toml
下找到此文件。
$ ll /etc/containerd/config.toml
在 Linux 上,containerd 的默认 CRI 套接字是 /run/containerd/containerd.sock
。 在 Windows 上,默认 CRI 端点是 npipe://./pipe/containerd-containerd
。
Step 2.2.1、配置 systemd
cgroup 驱动
结合 runc
使用 systemd
cgroup 驱动,在 /etc/containerd/config.toml
中设置:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
如果你使用 cgroup v2,则推荐 systemd
cgroup 驱动。
说明:
如果你使用RPM包安装 containerd,可能会发现其中默认禁止了 CRI 集成插件。
你需要启用 CRI 支持才能在 Kubernetes 集群中使用 containerd。 要确保 cri
没有出现在 /etc/containerd/config.toml
文件中 disabled_plugins
列表内。如果你更改了这个文件,也请记得要重启 containerd
。
如果你在初次安装集群后或安装 CNI 后遇到容器崩溃循环,则随软件包提供的 containerd 配置可能包含不兼容的配置参数。考虑按照 getting-started.md 中指定的 containerd config default > /etc/containerd/config.toml
重置 containerd 配置,然后相应地设置上述配置参数。
如果你应用此更改,请确保重新启动 containerd:
sudo systemctl restart containerd
当使用 kubeadm 时,请手动配置 kubelet 的 cgroup 驱动。
Step 2.2.2、重载沙箱(pause)镜像
在你的 containerd 配置中, 你可以通过设置以下选项重载沙箱镜像:
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.2"
一旦你更新了这个配置文件,可能就同样需要重启 containerd
:systemctl restart containerd
。
Step 2.2.3、containerd使用
containerd使用
如果你之前用过Docker,你只要稍微花5分钟就可以学会containerd了,接下来我们学习下containerd的使用。
其实只要把我们之前使用的docker命令改为crictl命令即可操作containerd,
比如查看所有运行中的容器;
crictl psCONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID4ca73ded41bb6 3b0b04aa3473f Less than a second ago Running helm 20 21103f00588723bb5767a81954 296a6d5035e2d About a minute ago Running coredns 1 af887263bd869a5e34c24be371 0346349a1a640 About a minute ago Running nginx 1 89defc6008501
查看所有镜像;
crictl imagesIMAGE TAG IMAGE ID SIZEdocker.io/library/nginx 1.10 0346349a1a640 71.4MBdocker.io/rancher/coredns-coredns 1.8.0 296a6d5035e2d 12.9MBdocker.io/rancher/klipper-helm v0.4.3 3b0b04aa3473f 50.7MBdocker.io/rancher/local-path-provisioner v0.0.14 e422121c9c5f9 13.4MBdocker.io/rancher/metrics-server v0.3.6 9dd718864ce61 10.5MBdocker.io/rancher/pause 3.1 da86e6ba6ca19 327kB
进入容器内部执行bash命令,这里需要注意的是只能使用容器ID,不支持使用容器名称;
crictl exec -it a5e34c24be371 /bin/bash
查看容器中应用资源占用情况,可以发现占用非常低。
crictl statsCONTAINER CPU % MEM DISK INODES3bb5767a81954 0.54 14.27MB 254B 14a5e34c24be371 0.00 2.441MB 339B 16总结
从Docker转型containerd非常简单,基本没有什么门槛。只要把之前Docker命令中的docker改为crictl基本就可以了,果然是同一个公司出品的东西,用法都一样。所以不管K8S到底弃用不弃用Docker,对我们开发者使用来说,基本没啥影响!
2.2、使用CRI-O作为K8S的容器运行时
本节包含安装 CRI-O 作为容器运行时的必要步骤。
要安装 CRI-O,请按照 CRI-O 安装说明执行操作。
2.2.1、cgroup 驱动
CRI-O 默认使用 systemd cgroup 驱动,这对你来说可能工作得很好。 要切换到 cgroupfs
cgroup 驱动,请编辑 /etc/crio/crio.conf
或在 /etc/crio/crio.conf.d/02-cgroup-manager.conf
中放置一个插入式配置,例如:
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"
你还应该注意当使用 CRI-O 时,并且 CRI-O 的 cgroup 设置为 cgroupfs
时,必须将 conmon_cgroup
设置为值 pod
。 通常需要保持 kubelet 的 cgroup 驱动配置(通常通过 kubeadm 完成)和 CRI-O 同步。
对于 CRI-O,CRI 套接字默认为 /var/run/crio/crio.sock
。
2.2.2、重载沙箱(pause)镜像
在你的 CRI-O 配置中, 你可以设置以下配置值:
[crio.image]
pause_image="registry.k8s.io/pause:3.6"
这一设置选项支持动态配置重加载来应用所做变更:systemctl reload crio
。 也可以通过向 crio
进程发送 SIGHUP
信号来实现。
2.3、使用Docker作为K8S的容器运行时
在没有特殊需求的情况下,还是推荐大家使用containerd 或 CRI-O等受支持的容器运行时软件。
如果您依赖Docker Engine,也可以使用cri-dockerd这样的软件来解决。不管您使用哪种方式,云君都建议您做好一些兼容性测试工作,以确保Kubernetes 1.24集群的正常运行。
参考:https://www.cnblogs.com/fenghua001/p/16849875.html
2.3.1、安装 Docker
[root@all ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
[root@all ~]# yum -y install docker-ce-18.06.1.ce-3.el7
[root@all ~]# systemctl enable docker && systemctl start docker
[root@all ~]# docker --version
Docker version 18.06.1-ce, build e68fc7a
2.3.2、安装cri-dockerd
方法一:
到下面的链接下载最新版cri-docker
https://github.com/Mirantis/cri-dockerd/releases
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.6/cri-dockerd-0.2.6.amd64.tgz
tar -xf cri-dockerd-0.2.6.amd64.tgz
cp cri-dockerd/cri-dockerd /usr/bin/
chmod +x /usr/bin/cri-dockerd
#配置启动文件
vim /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/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.8
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
StartLimitBurst=3
StartLimitInterval=60s
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
Delegate=yes
KillMode=process
[Install]
WantedBy=multi-user.target
#生成socket文件
vim /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
# 启动cri-docker并设置开机自动启动
systemctl daemon-reload ; systemctl enable cri-docker --now
systemctl is-active cri-docke
如果是多master 需要操作下面步骤
#先在master上解压出cri-docker,然后拷贝到其他节点
[root@k8s-master01 ~]# tar -zxf cri-dockerd-0.2.5.amd64.tgz
[root@k8s-master01 ~]# cp cri-dockerd/cri-dockerd /usr/bin/
[root@k8s-master01 ~/cri-dockerd]# scp /usr/bin/cri-dockerd root@k8s-node01:/usr/bin/
[root@k8s-master01 ~/cri-dockerd]# scp /usr/bin/cri-dockerd root@k8s-node02:/usr/bin/
#创建cri-docker启动文件,然后拷贝到其他节点
[root@k8s-master01 ~]# cat /usr/lib/systemd/system/cri-docker.service
[root@k8s-master01 ~]# cat /usr/lib/systemd/system/cri-docker.socket
方法二:
wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.2.6/cri-dockerd-0.2.6-3.el7.x86_64.rpm
rpm -ivh cri-dockerd-0.2.6-3.el7.x86_64.rpm
systemctl enable cri-docker
重载沙箱
vim /usr/lib/systemd/system/cri-docker.service # 修改如下
ExecStart=/usr/bin/cri-dockerd --network-plugin=cni --pod-infra-container-image=registry.aliyuncs.com/google_containers/pause:3.8 --container-runtime-endpoint fd://
systemctl start cri-docker
3、 所有节点安装 kubeadm、kubelet 和 kubectl
3.1、添加阿里云 YUM 软件源
设置仓库地址
[root@all ~]# cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://b9pmyelo.mirror.aliyuncs.com"]
}
EOF
添加kubernetes yum 源
[root@all ~]# cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes_aliyun]
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
[kubernetes_tuna]
name=kubernetes
baseurl=https://opentuna.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=0
EOF
3.2、安装 kubeadm, kubelet 和 kubectl
#这里安装的三个程序的版本,需要和最终安装的集群版本一致,如果对集群版本有要求,这里就需要指定版本安装
[root@all ~]# yum install -y kubelet kubeadm kubectl
#启动kubelet服务
[root@all ~]# systemctl start kubelet
[root@all ~]# systemctl enable kubelet
[root@all ~]# systemctl status kubelet
4、 初始化kubeadm(部署 Kubernetes Master节点)
4.1、在Master执行
由于默认拉取镜像地址 k8s.gcr.io 国内无法访问, 这里指定阿里云镜像仓库地址。
[root@master ~]#
kubeadm init \
--apiserver-advertise-address=192.168.245.100 \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--kubernetes-version v1.26.1
初始化参数详解
--apiserver-advertise-address string
设置 apiserver 绑定的 IP.(Master节点IP)
--image-repository string
选择拉取 control plane images 的镜像repo (default "k8s.gcr.io")
--kubernetes-version string
选择K8S版本. (default "stable-1")
--service-cidr string
指定service 的IP 范围. (default "10.96.0.0/12")
--pod-network-cidr string
指定 pod 的网络, control plane 会自动将 网络发布到其他节点的node,让其上启动的容器使用此网络
--apiserver-bind-port int32
设置apiserver 监听的端口. (默认 6443)
--apiserver-cert-extra-sans strings
api证书中指定额外的Subject Alternative Names (SANs) 可以是IP 也可以是DNS名称。 证书是和SAN绑定的。
--cert-dir string
证书存放的目录 (默认 "/etc/kubernetes/pki")
--certificate-key string
kubeadm-cert secret 中 用于加密 control-plane 证书的key
--config string
kubeadm 配置文件的路径.
--cri-socket string
CRI socket 文件路径,如果为空 kubeadm 将自动发现相关的socket文件; 只有当机器中存在多个 CRI socket 或者 存在非标准 CRI socket 时才指定.
--dry-run
测试,并不真正执行;输出运行后的结果.
--feature-gates string
指定启用哪些额外的feature 使用 key=value 对的形式。
--help -h
帮助文档
--ignore-preflight-errors strings
忽略前置检查错误,被忽略的错误将被显示为警告. 例子: 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.
--node-name string
指定node的名称,默认使用 node 的 hostname.
--service-dns-domain string
指定 service 的 dns 后缀, e.g. "myorg.internal". (default "cluster.local")
--skip-certificate-key-print
不打印 control-plane 用于加密证书的key.
--skip-phases strings
跳过指定的阶段(phase)
--skip-token-print
不打印 kubeadm init 生成的 default bootstrap token
--token string
指定 node 和control plane 之间,简历双向认证的token ,格式为 [a-z0-9]{6}\.[a-z0-9]{16} - e.g. abcdef.0123456789abcdef
--token-ttl duration
token 自动删除的时间间隔。 (e.g. 1s, 2m, 3h). 如果设置为 '0', token 永不过期 (default 24h0m0s)
--upload-certs
上传 control-plane 证书到 kubeadm-certs Secret.
–-node-name string
指定当前节点的名称。
4.2、使用 kubectl 工具:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
$ kubectl get nodes
5、 安装 Pod 网络插件( CNI)
$ kubectl apply – f
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kubeflannel.yml
确保能够访问到 quay.io 这个 registery。 如果 Pod 镜像下载失败, 可以改这个镜像地址
6、 加入 Kubernetes Node
( 1) 在 192.168.31.62/63( Node) 执行 向集群添加新节点, 执行在 kubeadm init 输出的 kubeadm join 命令:
$ kubeadm join 192.168.31.61:6443 --token esce21.q6hetwm8si29qxwn \
--discovery-token-ca-cert-hash
sha256:00603a05805807501d7181c3d60b478788408cfe6cedefedb1f97569708be9c5
7、 测试 kubernetes 集群
在 Kubernetes 集群中创建一个 pod, 验证是否正常运行:
$ kubectl create deployment nginx --image=nginx
$ kubectl expose deployment nginx --port=80 --type=NodePort
$ kubectl get pod,svc
访问地址: http://NodeIP:Port