基于 containerd 部署K8S

零、 环境介绍

  • kubernetes v 1.2.0
主机 ip 系统 kernel 配置 角色
k8s-master 192.168.100.250 CentOS 7.9 Linux 5.4.210-1.el7.elrepo.x86_64 2c4g 40GB Master
k8s-node1 192.168.100.251 CentOS 7.9 Linux 5.4.210-1.el7.elrepo.x86_64 2c4g 40GB Work
k8s-node2 192.168.100.252 CentOS 7.9 Linux 5.4.210-1.el7.elrepo.x86_64 2c4g 40GB Work

一、 基础环境配置

  • 一台或多台服务器
  • 内存4GB或更多,CPU2核或更多,硬盘30GB或更多
  • 所有机器之间网络互通
  • 可以访问外网,需要拉取镜像
  • 禁止swap分区

1.0 修改源

  • 三台服务器都需配置
    sed -i.bak \
    -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://mirror.centos.org/centos|baseurl=https://mirrors.ustc.edu.cn/centos-vault/centos|g' \
    /etc/yum.repos.d/CentOS-Base.repo

1.1 禁止 SWAP 分区

  • 三台服务器都需配置
    swapoff -a
    sed -ri 's/.*swap.*/#&/' /etc/fstab

1.2 关闭防火墙

  • 三台服务器都需配置
    systemctl stop firewalld iptables
    systemctl disable firewalld iptables

1.3 关闭 SeLinux

  • 三台服务器都需配置
    setenforce 0
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config

1.4 配置主机名

  • 三台服务器都需要配置

    主机 ip
    k8s-master 192.168.100.210
    k8s-node1 192.168.100.220
    k8s-node2 192.168.100.230

    hostnamectl set-hostname k8s-master

    cat >> /etc/hosts << EOF
    192.168.100.210 k8s-master
    192.168.100.220 k8s-node1
    192.168.100.230 k8s-node2
    EOF

1.5 配置时间同步

  • 三台服务器都需配置
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    systemctl enable chronyd --now

1.6 配置 ipvs 负载均衡

  • 三台服务器都需配置

  • 安装软件包
    yum install ipset ipvsadm conntrack

  • 配置 ip_vs

    cat > /etc/sysconfig/modules/ipvs.modules <<EOF
    # /bin/bash
    modprobe ip_vs
    modprobe ip_vs_rr
    modprobe ip_vs_wrr
    modprobe ip_vs_sh
    modprobe nf_conntrack
    EOF

    chmod 755 /etc/sysconfig/modules/ipvs.modules
  • 重新加载内核
    systemctl restart systemd-modules-load.service

  • 验证模块加载

    [root@k8s-master]# lsmod | grep ip_vs
    ip_vs_sh 16384 0
    ip_vs_wrr 16384 0
    ip_vs_rr 16384 0
    ip_vs 233472 6 ip_vs_rr,ip_vs_sh,ip_vs_wrr
    nf_conntrack 212992 3 nf_nat,nft_ct,ip_vs
    nf_defrag_ipv6 24576 2 nf_conntrack,ip_vs
    libcrc32c 16384 5 nf_conntrack,nf_nat,nf_tables,xfs,ip_vs

1.7 开启网络转发和桥接

  • 三台服务器都需配置

    cat >> /etc/sysctl.d/k8s.conf << EOF
    net.ipv4.ip_forward = 1
    net.bridge.bridge-nf-call-iptables = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    vm.swappiness = 0
    EOF

    sysctl --system

  • 验证配置

    sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward vm.swappiness
    [root@k8s-master ~]# sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward vm.swappiness
    net.bridge.bridge-nf-call-iptables = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward = 1
    vm.swappiness = 0
    [root@k8s-master ~]#

1.8 加载 br_netfilter 内核参数

  • 三台服务器都需配置

    有时候会碰到网桥转发参数设置失败

  • 设置开机自动加载

    cat >> /etc/sysconfig/modules/br_netfilter.modules << EOF
    #!/bin/bash
    modprobe br_netfilter
    modprobe overlay
    modprobe nf_conntrack

    chmod 755 /etc/sysconfig/modules/br_netfilter.modules
  • 加载内核
    systemctl restart systemd-modules-load.service

  • 验证

    [root@k8s-master ~]# lsmod | grep br
    br_netfilter 22256 0

二、 Containerd 部署

三台服务器都需要部署

  • 遵循 FHS 规范解压到 /usr/local/bin
  • Containerd 版本: v2.0.2

2.1 下载并安装

  • 下载地址: https://github.com/containerd/containerd/releases
    tar xzvf containerd-2.0.2-linux-amd64.tar.gz --strip-components=1 -C /usr/local/bin
    mkdir -p /etc/containerd
    /usr/local/bin/containerd config default > /etc/containerd/config.toml
    sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml

2.3 使用systemd管理

  • 创建文件: vim /usr/lib/systemd/system/containerd.service
    [Unit]
    Description=containerd container runtime
    Documentation=https://containerd.io
    After=network.target local-fs.target
    [Service]
    ExecStartPre=-/sbin/modprobe overlay
    ExecStart=/usr/local/bin/containerd
    Type=notify
    Delegate=yes
    KillMode=process
    Restart=always
    RestartSec=5
    LimitNPROC=infinity
    LimitCORE=infinity
    TasksMax=infinity
    OOMScoreAdjust=-999
    [Install]
    WantedBy=multi-user.target
    systemctl daemon-reload
    systemctl enable containerd --now

2.5 可能遇到的问题

问题: containerd.service: Main process exited, code=exited, status=2/INVALIDARGUMENT
解决: rm -rf /var/lib/containerd

三、 Crictl 和 Runc 部署

三台服务器都需要部署

  • Crictl 版本: v1.32.0
    https://github.com/kubernetes-sigs/cri-tools/releases

  • Runc 版本: v1.2.5
    https://github.com/opencontainers/runc/releases

  • 部署
    tar -xzvf crictl-v1.32.0-linux-amd64.tar.gz -C /usr/local/bin/
    chmod +x runc.amd64
    mv runc.amd64 /usr/local/bin/runc

  • 验证Crictl 和 Runc 版本

    [root@k8s-node2 bin]# ll /usr/local/bin/
    total 154912
    -rwxr-xr-x 1 root root 55969576 Jan 14 13:32 containerd
    -rwxr-xr-x 1 root root 7725208 Jan 14 13:32 containerd-shim-runc-v2
    -rwxr-xr-x 1 root root 21467457 Jan 14 13:32 containerd-stress
    -rwxr-xr-x 1 1001 127 40076447 Dec 9 17:09 crictl
    -rwxr-xr-x 1 root root 22200641 Jan 14 13:32 ctr
    -rwxr-xr-x 1 root root 11172320 Feb 25 04:07 runc
    [root@k8s-node2 bin]#
    [root@k8s-node2 bin]# crictl --version
    crictl version v1.32.0
    [root@k8s-node2 bin]#
    [root@k8s-node2 bin]# runc --version
    runc version 1.2.5
    commit: v1.2.5-0-g59923ef1
    spec: 1.2.0
    go: go1.22.12
    libseccomp: 2.5.5
    [root@k8s-node2 bin]#

四、 kubeadm kubectl kubelet 部署

三台服务器都需部署

  • 添加阿里源

    [kubernetes]
    name=Kubernetes
    baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/
    enabled=1
    gpgcheck=1
    gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.28/rpm/repodata/repomd.xml.key
  • 安装指定版本 v1.28.15

    yum install kubectl-1.28.15 kubeadm-1.28.15 kubelet-1.28.15 --nogpgcheck

  • 配置 kubelet 参数

    echo "KUBELET_EXTRA_ARGS=\"--cgroup-driver=systemd\"" > /etc/sysconfig/kubelet

  • 配置 kubelet 自启

    systemctl enable kubelet --now

五、 Master 节点初始化

仅在Master节点配置

  • 获取镜像

    kubeadm config images list
    图

  • 下载镜像, 有需要可以更换源下载

    kubeadm config images pull

  • 初始化 Master

    kubeadm init \
    --apiserver-advertise-address=192.168.100.250 \
    --control-plane-endpoint=k8s-master \
    --image-repository registry.k8s.io \
    --kubernetes-version v1.28.15 \
    --service-cidr=10.244.0.0/16 \
    --pod-network-cidr=192.168.0.0/16 \
  • 看到如下界面表示初始化成功
    图

  • 检查各容器是否正常
    crictl ps -a
    图

  • 配置参数
    mkdir -p $HOME/.kube
    cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    chown $(id -u):$(id -g) $HOME/.kube/config
    echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> /etc/profile

  • 最终检查

    Nodes 的状态是 NotReady, 这点我们后面在解决
    图

六、 Node 节点加入 Master

在两台 node 节点上执行

  • 根据Master初始化成功的信息中, 直接复制加入命令, 注意没有 --control-plane

    kubeadm join k8s-master:6443 --token tpb7dk.73uvwnycqhjo9bl9 \
    --discovery-token-ca-cert-hash sha256:5f8366652dedb0c8a1dbd97a5992321fe4e9a2ee059c14de64f053360c5e9065
  • 验证node节点的加入
    在 Node 节点执行
    图

  • 在 Master 节点执行
    kubectl get nodes
    图

初始化 master 的时候生成了 token, 有效期24小时, 如果忘记了初始 token, 可以使用以下方法重新获取

  • 输出当前 token
    kubeadm token list

  • 重新生成 token
    kubeadm token create --print-join-command

  • 获取集群根证书的哈希值

    openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | \
    openssl rsa -pubin -outform der 2>/dev/null | \
    openssl dgst -sha256 -hex | \
    sed 's/^.* //'

七、 Calico 网络插件部署

仅在 Master 节点配置

注意到 kubectl get nodes 的执行结果中, STATUS 状态都是 NotRead

  • 创建资源 Tigera Operator
    kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml
    图

  • 下载配置文件, 修改 CIDRPOD 的网段 10.244.0.0/16
    wget https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/custom-resources.yaml
    图

  • 创建 Calico 自定义资源, 注意 Ready 的状态
    kubectl create -f custom-resources.yaml
    watch kubectl get pods -n calico-system
    图

  • 查看pods详细信息
    kubectl get pods -n kube-system -o wide
    图

  • 测试域名解析
    kubectl get svc -n kube-system
    dig baidu.com @10.96.0.10
    图

八、 应用部署测试

使用 nginx 测试部署

  • 配置文件如下

    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: nginx
    labels:
    app: nginx
    spec:
    ports:
    - port: 80
    name: web
    selector:
    app: nginx
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: web
    spec:
    selector:
    matchLabels:
    app: nginx
    replicas: 1
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    name: web
  • 构建应用
    kubectl apply -f nginx.yaml

  • 服务地址
    kubectl get pods -o wide
    kubectl get service
    图

  • 访问测试
    图