一、前言
在今年5月3日的时候Kubernetes (以下简称k8s)官方已经发布了1.24版本,此版本带来了 46 项增强,在这 46 项增强功能中,13 项正在升级到稳定版,14 项是不断改进的现有功能,13 项是全新的,6 项是已弃用的功能。其中,最大的变动是删除了Dockershim,这意味着Dockershim作为k8s对接 Docker到CRI接口上的一个垫片时代已经结束了,对我们讲是一个新的开始,我们可以拥抱更多容器运行时的支持,例如比较优秀的containerd、CRI-O等,今天我们来排一下基于containerd部署的k8s集群。
二、集群架构
三、基础环境搭建
在生产环境中,k8s的基础环境搭建是必不可少的步骤,若是基础环境搭建的不好,后期可能会存在各种各样的隐患,所以基础环境搭建尤为重要。
3.1 主机清单
宿主机系统 |
k8s集群角色 |
服务器 |
主机名 |
容器 |
Centos7.6 | 控制节点 | 10.0.8.2 | ks-m1 | docker |
Centos7.6 | 工作节点 | 10.0.8.7 | ks-n1 | docker |
版本说明
- contained version:1.6.8
- kubeadm version: 1.24.4
- kubectl version: 1.24.4
- kubelet version: 1.24.4
3.2 配置主机名
#在10.0.8.2上执行如下: $ hostnamectl set-hostname ks-m1 && bash #在10.0.8.7上执行如下: $ hostnamectl set-hostname ks-n1 && bash
3.3 配置hosts文件
#修改ks-m1、ks-n1机器的/etc/hosts文件,增加如下四行: 10.0.8.2 ks-m1 10.0.8.7 ks-n1 或 cat >> /etc/hosts << EOF 10.0.8.2 ks-m1 10.0.8.7 ks-n1 EOF
3.4 关闭防火墙、selinux、关闭交换分区
##关闭防火墙 $ systemctl stop firewalld ##禁止防火墙开机启动 $ systemctl disable firewalld ##永久关闭selinux 注:重启机器后,selinux配置才能永久生效 $ sed -i 's/enforcing/disabled/' /etc/selinux/config ##临时关闭selinux 执行getenforce 显示Disabled说明selinux已经关闭 $ setenforce 0 ##永久关闭交换分区swap 注:重启机器后,才能永久生效 $ sed -ri 's/.*swap.*/#&/' /etc/fstab ##临时关闭交换分区swap $ swapoff -a
注意:每台机器都要执行
3.5 升级系统内核
在升级内核十分重要,低版本的内核下k8s集群不稳定,且对插件的兼容性不好,例如3.10版本的内核不支持网络插件Calico3.23版本等。
共有两种开机引导模式:bios和uefi,其中uefi引导模式下需要关闭安全引导,否则无法正常开机。
1)导入public key
$ rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
2)安装epel源
$ yum install https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm -y
3)查看可用版本内核
$ yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
4)选择安装lt最新版本
$ yum --enablerepo=elrepo-kernel install kernel-lt -y
关于内核种类:
kernel-ml中的ml是英文【 mainline stable 】的缩写,elrepo-kernel中罗列出来的是最新的稳定主线版本。
kernel-lt 中的lt是英文【 long term support 】的缩写,elrepo-kernel中罗列出来的长期支持版本。(推荐)
5)查看系统上可以用的内核
bios模式下:
$ awk -F\' '$1=="menuentry " {print i++ " : " $2}' /etc/grub2.cfg
uefi模式下:
$ awk -F\' '$1=="menuentry " {print i++ " : " $2}' /boot/efi/EFI/centos/grub.cfg
注:前面的0 1 2代表编号。
6)设置内核启动顺序
$ grub2-set-default 0
7)重新创建内核配置
bios模式下:
$ grub2-mkconfig -o /boot/grub2/grub.cfg
uefi模式下:
$ grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
8)重启验证
$ reboot $ uname -r
注:内核升级完成后需要重启主机,然后使用uname -r查看内核版本是否升级成功。
3.6 修改内核参数
在内核版本升级后再操作。
##加载br_netfilter模块 modprobe br_netfilter #验证模块是否加载成功 lsmod | grep br_netfilter ##修改内核参数 cat > /etc/sysctl.d/k8s.conf << EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 vm.swappiness = 0 EOF $ vm.swappiness = 0 # 禁止使用swap空间,只有当系统OOM时才允许使用它 ##生效 $ sysctl --system 或 sysctl -p /etc/sysctl.d/k8s.conf
- net.bridge.bridge-nf-call-iptables:开启桥设备内核监控(ipv4)
- net.ipv4.ip_forward:开启路由转发
- net.bridge.bridge-nf-call-ip6tables:开启桥设备内核监控(ipv6)
以上3项为必须参数,其他参数可根据需要添加。
3.7配置yum源(采用阿里云repo源)
##下载常用的软件 $ yum clean all && yum makecache && yum repolist $ yum install -y vim net-tools bash-completion wget lrzsz ##配置国内阿里云docker的repo源 $ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3.8配置安装k8s组件需要的阿里云的repo源
$ cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=0 repo_gpgcheck=0 gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg EOF
3.9配置时间同步
##安装ntpdate命令 $ yum install ntpdate -y ##跟网络源做同步 $ ntpdate cn.pool.ntp.org ##把时间同步做成计划任务 $ crontab -e ##填入一下内容 $ * */1 * * * /usr/sbin/ntpdate cn.pool.ntp.org ##重启crond服务 $ service crond restart 或者利用chronyd ##安装chronyd $ yum install -y chronyd ##启动chronyd及加入开机自启 $ systemctl start chronyd && systemctl enable chronyd #修改/etc/chrony.conf配置文件,同步服务器地址为阿里云,增加一行(server ntp1.aliyun.com iburst,其余服务地址注释了) $ server ntp1.aliyun.com iburst
3.10配置IPVS
$ yum install -y ipvsadm ipset sysstat conntrack libseccomp $ cat > /etc/sysconfig/modules/ipvs.modules <<EOF #!/bin/bash ipvs_modules="ip_vs ip_vs_lc ip_vs_wlc ip_vs_rr ip_vs_wrr ip_vs_lblc ip_vs_lblcr ip_vs_dh ip_vs_sh ip_vs_fo ip_vs_nq ip_vs_sed ip_vs_ftp nf_conntrack ip_tables ip_set xt_set ipt_set ipt_rpfilter ipt_REJECT ipip " for kernel_module in \${ipvs_modules}; do /sbin/modinfo -F filename \${kernel_module} > /dev/null 2>&1 if [ $? -eq 0 ]; then /sbin/modprobe \${kernel_module} fi done EOF $ chmod 755 /etc/sysconfig/modules/ipvs.modules $ sh /etc/sysconfig/modules/ipvs.modules $ lsmod | grep ip_vs
dummy0网卡和kube-ipvs0网卡:在安装k8s集群时,启用了ipvs的话,就会有这两个网卡。(将service的IP绑定在kube-ipvs0网卡上)
3.11安装Containerd(二进制)
1)下载二进制包
$ wget https://github.com/containerd/containerd/releases/download/v1.6.8/cri-containerd-1.6.8-linux-amd64.tar.gz $ tar zxvf cri-containerd-1.6.8-linux-amd64.tar.gz $ ls -l drwxr-xr-x 4 root root 51 4月 26 07:52 etc drwxr-xr-x 4 root root 35 4月 26 07:51 opt drwxr-xr-x 3 root root 19 4月 26 07:50 usr
etc目录:主要为containerd服务管理配置文件及cni虚拟网卡配置文件;
opt目录:主要为gce环境中使用containerd配置文件及cni插件;
usr目录:主要为containerd运行时的二进制文件,包含runc;
2)拷贝二进制可执行文件到$PATH
中
$ ls usr/local/bin/ containerd containerd-shim containerd-shim-runc-v1 containerd-shim-runc-v2 containerd-stress crictl critest ctd-decoder ctr $ cp usr/local/bin/* /usr/local/bin/
containerd 的安装包中一共有五个文件,通过上面的命令它们被安装到了 /usr/local/bin 目录中:
containerd:即容器的运行时,以 gRPC 协议的形式提供满足 OCI 标准的 API
containerd-release:containerd 项目的发行版发布工具
containerd-stress:containerd压力测试工具
containerd-shim:这是每一个容器的运行时载体,我们在 docker 宿主机上看到的 shim 也正是代表着一个个通过调用 containerd 启动的 docker 容器。
ctr:它是一个简单的 CLI 接口,用作 containerd 本身的一些调试用途,投入生产使用时还是应该配合docker 或者 cri-containerd 部署。
3)创建初始配置文件
Containerd 的默认配置文件为 /etc/containerd/config.toml
$ mkdir -p /etc/containerd/ $ containerd config default > /etc/containerd/config.toml #创建默认的配置文件
4)修改配置
- 替换镜像源
由于国内环境原因我们需要将 sandbox_image 镜像源设置为阿里云google_containers镜像源。
$ sed -i "s#k8s.gcr.io/pause#registry.cn-hangzhou.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml #等同于: $ vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6"
- 配置镜像加速
$ vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://cekcu3pt.mirror.aliyuncs.com"]
- 配置驱动器
Containerd 和 Kubernetes 默认使用旧版驱动程序来管理 cgroups,但建议在基于 systemd 的主机上使用该驱动程序,以符合 cgroup 的“单编写器”规则。
$ sed -i 's#SystemdCgroup = false#SystemdCgroup = true#g' /etc/containerd/config.toml #等同于 $ vim /etc/containerd/config.toml [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true
5)创建服务管理配置文件
拷贝服务管理配置文件到/usr/lib/systemd/system/目录
$ grep -v ^# etc/systemd/system/containerd.service $ mv etc/systemd/system/containerd.service /usr/lib/systemd/system/containerd.service
6)启动 containerd 服务
$ systemctl daemon-reload $ systemctl enable --now containerd.service $ systemctl status containerd.service $ containerd --version #查看版本 containerd github.com/containerd/containerd v1.6.3 f830866066ed06e71bad64871bccfd34daf6309c
7)安装runc(二进制)
由于二进制包中提供的runC默认需要系统中安装seccomp支持,需要单独安装,且不同版本runC对seccomp版本要求不一致,所以建议单独下载runC 二进制包进行安装,里面包含了seccomp模块支持。下载地址:https://github.com/opencontainers/runc/releases
Runc是真正运行容器的工具
$ chmod +x runc.amd64 $ mv runc.amd64 /usr/bin/runc $ runc -version #出现以下说明安装没有问题 runc version 1.1.4 commit: v1.1.4-0-g5fd4c4d1 spec: 1.0.2-dev go: go1.17.10 libseccomp: 2.5.4 ##出现以下说明依赖确实或者版本不支持 runc: symbol lookup error: runc: undefined symbol: seccomp_notify_respond
【报错原因】缺少依赖包libseccomp(2.4
以上版本)安全计算模式。解决办法:
$ wget http://rpmfind.net/linux/centos/8-stream/BaseOS/x86_64/os/Packages/libseccomp-2.5.1-1.el8.x86_64.rpm $ rpm -ivh libseccomp-2.5.1-1.el8.x86_64.rpm $ rpm -qa | grep libseccomp libseccomp-2.5.1-1.el8.x86_64 $ runc -version runc version 1.1.2 commit: v1.1.2-0-ga916309f spec: 1.0.2-dev go: go1.17.11 libseccomp: 2.5.1
配置crictl客户端
$ mv etc/crictl.yaml /etc/ $ cat /etc/crictl.yaml runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///var/run/containerd/containerd.sock timeout: 10 debug: false
3.12下载并安装kubeadm、kubectl、kubelet
$ yum install -y kubelet-1.24.4 kubeadm-1.24.4 kubectl-1.24.4 $ systemctl enable kubelet && systemctl start kubelet && systemctl status kubelet #上面可以看到kubelet状态不是running状态,这个是正常的,不用管,等k8s组件起来这个kubelet就正常了。 ##注:每个软件包的作用 Kubeadm: kubeadm是一个工具,用来初始化k8s集群的 kubelet: 安装在集群所有节点上,用于启动Pod的 kubectl: 通过kubectl可以部署和管理应用,查看各种资源,创建、删除和更新各种组件
3.13设置Table键补全
让命令可用自动table键进行补全,对新手无法记住命令提供很好的支持,所在主机进行该操作方可使用table补全。
- Kubectl命令补全:
$ kubectl completion bash > /etc/bash_completion.d/kubelet
- Kubeadm命令补全:
$ kubeadm completion bash > /etc/bash_completion.d/kubeadm
四、初始化master节点
4.1 检测安装环境
检测主机环境是否达到集群的要求,可根据结果提示进行逐一排除故障
$ kubeadm init --dry-run
4.2 镜像下载/导入
1)列出需要使用的镜像列表
$ kubeadm config images list
2)拉取镜像
$ kubeadm config images pull \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.24.4
--image-repository: 从哪个地方下载镜像(默认"k8s.gcr.io",但k8s.gcr.io国内无法访问);
--kubernetes-version: 指定kubernetes集群的镜像版本;
4.3 创建配置文件
创建默认的配置文件
$ kubeadm config print init-defaults > kubeadm-init.yaml
修改配置文件
$ cat kubeadm-init.yaml apiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: 10.0.8.2 #修改为控制节点IP(VIP) bindPort: 6443 nodeRegistration: criSocket: /run/containerd/containerd.sock #使用containerd为容器运行时 imagePullPolicy: IfNotPresent name: ks-m1 #修改为控制节点主机名 taints: null --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: {} etcd: local: dataDir: /var/lib/etcd imageRepository: registry.aliyuncs.com/google_containers #修改为阿里镜像地址 kind: ClusterConfiguration kubernetesVersion: 1.24.4 #版本 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 #指定Pod网段 serviceSubnet: 10.96.0.0/12 #指定Service网段 scheduler: {} --- apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs --- apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration cgroupDriver: systemd
4.4 初始化
$ kubeadm init --config kubeadm-init.yaml
显示如下说明安装成功:
注:该token 有效期为24小时。参数 --control-plane 就是加入控制节点,不带该参数就是加入工作节点。
4.5 环境配置
根据初始化成功后的提示对集群进行基础的配置。
$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config $ export KUBECONFIG=/etc/kubernetes/admin.conf $ echo "KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bashrc && source ~/.bashrc $ kubectl get nodes NAME STATUS ROLES AGE VERSION ks-m1 NotReady control-plane,master 3m3s v1.22.12
查看集群状态:
4.6 集群重置(可选)
初始化master有问题,可将集群重置,再次初始化master
$ kubeadm reset
五、扩展node节点
扩展node节点比较简单,通过以下命令即可:
kubeadm join 10.0.8.2:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:1688c61dd7f6dfee929b94b154866d099a164eba4870d09c82b12425bdd09ba9
查看集群状态:
$ kubectl get nodes
如下所示:
通过查看集群状态可以看到,状态为NotReady
,是因为还未安装网络插件,安装网络插件后就正常了,且node的点的角色为空,<none>就表示这个节点是工作节点。 按照如下方法,可以把ks-n1的ROLES
变成work
:
$ kubectl label node ks-n1 node-role.kubernetes.io/worker=worker
六、安装插件
6.1 下载Calico网络插件文件
下载地址:
$ curl https://projectcalico.docs.tigera.io/archive/v3.23/manifests/calico.yaml -O ##或者 $ wget https://docs.projectcalico.org/v3.23/manifests/calico.yaml --no-check-certificat
调整calico.yaml如下:
#新增两行配置 直接配置通配符 :value: "interface=eth.*" - name: IP_AUTODETECTION_METHOD value: "interface=eth.*"
注意:在安装calico网络时,默认安装是IPIP网络。calico.yaml文件中,将CALICO_IPV4POOL_IPIP的值修改成 "off",就能够替换成BGP网络。eth.*是根据自己机器的网络来调整的。这样可以避很多calico网络错误。如下:
6.2 提前下载Calico镜像
$ grep image calico.yaml
##预先下载calico相关的镜像 $ ctr images pull docker.io/calico/cni:v3.23.3 $ ctr images pull docker.io/calico/node:v3.23.3 $ ctr images pull docker.io/calico/kube-controllers:v3.23.3
6.3 安装Calico网络插件
##在其中一个master节点执行即可 $ kubectl apply -f calico.yaml
如下:
查看node节点和pod状态:
$ kubectl get nodes $ kubectl get pods -n kube-system
6.4 安装CoreDNS域名解析插件
在kubeadm
安装的k8s集群中,安装Calico
网络插件后会自动安装CoreDNS
插件。
6.5 安装Metrics数据采集插件
metrics-server
是一个集群范围内的资源数据集和工具,同样的,metrics-server
也只是显示数据,并不提供数据存储服务,主要关注的是资源度量 API 的实现,比如 CPU、文件描述符、内存、请求延时等指标,metric-server 收集数据给 k8s 集群内使用,如 kubectl,hpa,scheduler 等!
1)下载yaml文件
##下载最新版本的yaml文件 $ https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml ##指定下载v0.4.1版本 $ https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.4.1/components.yaml
2)修改yaml文件
$ mv components.yaml metrics-server.yaml $ vim metrics-server.yaml ... containers: - args: - --cert-dir=/tmp - --secure-port=4443 - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname - --kubelet-use-node-status-port - --metric-resolution=15s - --kubelet-insecure-tls #跳过验证SSL证书
注:将镜像k8s.gcr.io/metrics-server/metrics-server:v0.6.1替换为registry.aliyuncs.com/google_containers/metrics-server:v0.6.1
3)提前下载镜像
$ grep image: metrics-server.yaml #查看需要的镜像 image: registry.aliyuncs.com/google_containers/metrics-server:v0.6.1 $ ctr images pull registry.aliyuncs.com/google_containers/metrics-server:v0.6.1
4)调整apiserver的配置
需要在kube-apiserver
的配置文件中添加–enable-aggregator-routing=true参数来启用聚合认证。
vim /etc/kubernetes/manifests/kube-apiserver.yaml
##增加如下内容: - --enable-aggregator-routing=true
5)更新apiserver的配置
$ kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml pod/kube-apiserver created $ kubectl get pods -n kube-system
注:把CrashLoopBackOff状态的pod删除,删除后k8s会重新创建。
$ kubectl delete pods kube-apiserver -n kube-system pod "kube-apiserver" deleted
6)安装metrics-server
$ kubectl apply -f metrics-server.yaml serviceaccount/metrics-server created clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created clusterrole.rbac.authorization.k8s.io/system:metrics-server created rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created service/metrics-server created deployment.apps/metrics-server created apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
## 查看pod状态 $ kubectl get pods -n kube-system
7)查看节点资源
$ kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% ks-m1 252m 6% 1787Mi 11% ks-n1 272m 1% 2722Mi 45%
七、集群验证
通过以下命令进行集群验证:
$ kubectl get node