Skip to content

基于 Containerd 安装 Kubernetes(v1.25)

第一章:环境规划

1.1 集群类型

  • Kubernetes 集群大致分为两类:一主多从和多主多从。
    • 一主多从(单 master ):一个 Master 节点和多台 Node 节点,搭建简单,但是有单机故障风险,适合用于测试环境。
    • 多主多从(高可用):多台 Master 节点和多台 Node 节点,搭建麻烦,安全性高,适合用于生产环境。
  • 单 master 的架构图:

1679282313695-b1322714-8d71-4c3f-9aed-adbf05701446.png

  • 高可用集群的架构图:

1679282317330-55731dd9-e7d8-4dd1-a9fb-8e05e2ee9e61.png

1679282322328-5c3329e6-8061-4496-8a92-034e5f4d949f.png

1.2 主机规划

  • 本次采用单 master 搭建的方式:
角色 IP 地址 操作系统 配置 hostname
master 192.168.68.20 AlmaLinux 9 2核CPU,3G内存,50G硬盘 k8s-master
node 192.168.68.21 AlmaLinux 9 2核CPU,3G内存,50G硬盘 k8s-node1
node 192.168.68.22 AlmaLinux 9 2核CPU,3G内存,50G硬盘 k8s-node2

第二章:前置准备

2.1 查看系统内核

  • 查看当前系统的版本:
cat /etc/redhat-release

1679282344734-e5a78340-58f8-40c5-9877-085addd73406.gif

  • 查看当前系统的内核:
uname -sr

1679282380504-ac600dba-a0b2-48ed-bd30-56d15ab29dc6.gif

从图中,可以知道 AlmaLinux 9 的内核版本不是很低,所以无需升级。

  • 更新系统组件以及安装开发工具:
dnf -y update \
    && dnf -y groupinstall "Development Tools" \
    && dnf -y install epel-release

1679282395165-9c6e3930-c531-41de-933d-df66eec0861e.gif

2.2 设置主机名

  • 命令:
hostnamectl set-hostname <hostname>
  • 示例:
# 192.168.68.20
hostnamectl set-hostname k8s-master
# 192.168.68.21
hostnamectl set-hostname k8s-node1
# 192.168.68.22
hostnamectl set-hostname k8s-node2

1679282403331-00b81965-a82b-467a-b28a-14c3da6b9de5.gif

2.3 主机名解析

  • 为了方便后面集群节点间的直接调用,需要配置一下主机名解析,企业中推荐使用内部的 DNS 服务器:
cat >> /etc/hosts << EOF
127.0.0.1   $(hostname)
192.168.68.20 k8s-master
192.168.68.21 k8s-node1
192.168.68.22 k8s-node2
EOF

1679282418776-aa1ea066-fd80-4ab7-94f2-69775a00cad6.gif

2.4 关闭防火墙

  • 学习阶段可以关闭防火墙,并且公有云上也没有防火墙,只有安全组。
# 查看防火墙状态
systemctl status firewalld
# 临时关闭防火墙
systemctl stop firewalld
# 禁止开机自动启动防火墙
systemctl disable firewalld
# 查看防火墙状态
systemctl status firewalld

1679282428369-ccce236f-eb25-442a-8363-9029bea2a0de.gif

2.5 时间同步(公有云跳过)

  • Kubernetes 要求集群中的节点时间必须精确一致,所以在每个节点上添加时间同步:
# 安装
dnf -y install chrony
# 启动并设置开机自启
systemctl enable chronyd  --now
# 查看同步状态
chronyc sources

1679282436199-fd76acb9-40e1-4eef-95d3-9fb5da4b9333.gif

2.6 关闭 SELinux

  • 容器虚拟化需要关闭 SELinux:
# 查看 SELinux 是否开启
getenforce
# 查看 SELinux 是否开启
cat /etc/selinux/config
# 永久关闭 SELinux ,需要重启
sed -i 's/enforcing/disabled/' /etc/selinux/config
# 关闭当前会话的 SELinux ,重启之后无效
setenforce 0
# 查看 SELinux 是否开启
cat /etc/selinux/config

1679282444578-25f6ac3b-d4f8-4e17-908b-3e49b2e25afa.gif

2.7 关闭 swap 分区

  • 容器虚拟化需要关闭 swap 分区:
# 查看 swap 分区是否存在
free -h
# 关闭当前会话的 swap ,重启之后无效
swapoff -a
# 永久关闭 swap ,需要重启
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 查看 swap 分区是否存在
free -h

1679282453294-8b3accec-3312-4945-b60f-125c1cbbaeb9.gif

2.8 将桥接的 IPv4 流量传递到 iptables 的链

  • 加载模块:
# 开机自动启动
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
# 激活模块
modprobe overlay
modprobe br_netfilter
# 重启系统服务
systemctl restart systemd-modules-load.service
  • 设置所需的 sysctl 参数,参数在重新启动后保持不变:
# 如果有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g" /etc/sysctl.d/k8s.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g"  /etc/sysctl.d/k8s.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g" /etc/sysctl.d/k8s.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g"  /etc/sysctl.d/k8s.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g"  /etc/sysctl.d/k8s.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g" /etc/sysctl.d/k8s.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g" /etc/sysctl.d/k8s.conf

# 可能没有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.d/k8s.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.d/k8s.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.d/k8s.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.d/k8s.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.d/k8s.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.d/k8s.conf
echo "net.ipv6.conf.all.forwarding = 1"  >> /etc/sysctl.d/k8s.conf
  • 应用而不重新启动:
sysctl --system
  • 通过运行以下指令确认 br_netfilteroverlay 模块被加载:
lsmod | grep br_netfilter \
    && lsmod | grep overlay
  • 通过运行以下指令确认 net.bridge.bridge-nf-call-iptablesnet.bridge.bridge-nf-call-ip6tablesnet.ipv4.ip_forward 系统变量的 sysctl 配置中被设置为 1:
sysctl net.bridge.bridge-nf-call-iptables \
    net.bridge.bridge-nf-call-ip6tables \
    net.ipv4.ip_forward

1679282466334-e0bd232b-8fe6-4682-b327-c81038c30904.gif

2.19 重启系统(可选)

  • 重启系统,以便永久配置生效(不重启也是可以的,下次开机永久配置自动生效):
reboot

1679282470265-8cf0e889-4b86-43f3-9153-a1ce374c5860.gif

第三章:安装 Containerd

3.1 Kubernetes 集群的创建方案

  • 示意图:

1679282473582-2b4e42f1-5b01-4fb5-8024-847735fbf508.png

  • 方式 1:Containerd,默认情况下,Kubernetes 在创建集群的时候,使用的就是 Containerd 方式。
  • 方式 2:Docker,Docker 使用的普及率较高,虽然 Kubernetes-v1.24 默认情况下废弃了 kubelet 对于 Docker 的支持,但是我们还可以借助于 Mirantis 维护的 cri-dockerd 插件方式来实现 Kubernetes 集群的创建。Docker Engine 没有实现 CRI, 而这是容器运行时在 Kubernetes 中工作所需要的。 为此,必须安装一个额外的服务 cri-dockerd。 cri-dockerd 是一个基于传统的内置 Docker 引擎支持的项目, 它在 1.24 版本从 kubelet 中移除。
  • 方式 3::CRI-O,CRI-O 的方式是 Kubernetes 创建容器最直接的一种方式,在创建集群的时候,需要借助于 cri-o 插件的方式来实现 Kubernetes 集群的创建。

注意:本次采用的是 Containerd 的方式,并且不会在集群中安装 Docker(当然,你可以在集群中安装 Docker);因为,Kubernetes 已经提供了操作容器的客户端工具,和 Docker 的 cli 差不多。

3.2 Docker 的运行机制

  • Docker 的运行机制:

1679282481340-24253d49-9114-49b5-bd55-6e6f1d5168ae.png

由上图可知,Docker 依赖于 Containerd ;当然,目前 Containerd 是 Docker 维护的,对于目前的 Kubernetes 而言,我们只需要安装 Containerd  即可。

3.3 安装和配置 Containerd

  • 设置镜像源:
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

1679282519375-20fc2688-b811-4769-8750-c288d48f1e3e.gif

  • 安装 Containerd:
dnf -y install containerd.io \
        --allowerasing # 此参数的意思是将冲突的依赖删除

1679282524903-8ba0d95e-def2-4ef5-9f4b-21e798da78b9.gif

  • 配置 Containerd 的命令行工具 (重要):
cat << EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: "unix:///run/containerd/containerd.sock"
image-endpoint: "unix:///run/containerd/containerd.sock"
debug: false
pull-image-on-create: true
disable-pull-on-run: false
EOF

1679282533603-b74afb52-970a-45bb-9e79-9f3960f4ad70.gif

  • 利用 containerd 的客户端工具 ctr 验证是否成功:
containerd --version
ctr version

1679282537946-1200c89a-989b-4f01-938c-3d55a8e5a445.gif

  • 查询 containerd 的状态并停止 containerd:
systemctl status containerd
systemctl stop containerd

1679282546492-a6ab2d93-f2a3-4fdb-8935-9d67181498dc.gif

  • 修改 containerd 配置,将 sandbox_image 镜像源设置为阿里云 google_containers 镜像源(国内网络需要):
cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
containerd config default > /etc/containerd/config.toml
# 修改 /etc/containerd/config.toml 文件后,要将 docker、containerd 停止后,再启动
sed -i "s#registry.k8s.io/pause#registry.cn-hangzhou.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml
# 配置 containerd cgroup 驱动程序 systemd
sudo sed -i "s#SystemdCgroup = false#SystemdCgroup = true#g" /etc/containerd/config.toml \
    && grep SystemdCgroup /etc/containerd/config.toml

1679282557346-a503c98b-a1a7-4916-9eef-205f42afd714.gif

  • 镜像加速(可选):
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://du3ia00u.mirror.aliyuncs.com", "https://registry-1.docker.io"]

1679282565476-60f00c94-b073-4179-880a-1ecd369ab975.gif

  • 忽略证书验证(可选):
vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.configs]
    # 增加如下的两行
    [plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.68.100:8001".tls]
        insecure_skip_verify = true
  • 启动并设置开机自动启动 Containerd 服务:
systemctl enable --now containerd

1679282573360-f29bd0b6-da7a-48d9-b0df-4f762ef01ab9.gif

3.4 安装 Docker(可选)

  • 卸载旧版本的 Docker:
dnf -y remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
  • 安装 Docker :
dnf -y install docker-ce \
        docker-ce-cli \
        docker-buildx-plugin \
        docker-scan-plugin \
        docker-compose-plugin \
        --allowerasing # 此参数的意思是将冲突的依赖删除
  • 启动 Docker :
systemctl enable --now docker
  • 阿里云镜像加速:
sudo mkdir -pv /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "exec-opts": ["native.cgroupdriver=systemd"], 
  "registry-mirrors": [
    "https://du3ia00u.mirror.aliyuncs.com",
    "https://docker.m.daocloud.io",
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.nju.edu.cn",
    "https://docker.mirrors.sjtug.sjtu.edu.cn"
  ],
  "live-restore": true,
  "log-driver":"json-file",
  "log-opts": {"max-size":"500m", "max-file":"3"},
  "max-concurrent-downloads": 10,
  "max-concurrent-uploads": 5,
  "storage-driver": "overlay2"
}
EOF
systemctl daemon-reload \
    && systemctl restart docker

第四章:安装 Kubernetes

4.1 添加阿里云的 Kubernetes 的 YUM 源

  • 由于 Kubernetes 的镜像源在国外,非常慢,这里切换成国内的阿里云镜像源(三台机器均需执行下面命令):
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
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 https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

1679282587878-51b1d5b1-e8b0-4013-ae4b-733788f2633f.gif

4.2 安装 kubelet 、kubeadm 和  kubectl

  • 所有节点(三台机器)均需要 kubelet 、kubeadm 和  kubectl :
dnf install -y kubelet-1.25.7 kubeadm-1.25.7 kubectl-1.25.7 \
        --disableexcludes=kubernetes

1679282597889-4eb9e542-ba18-4812-8636-97b7c5cf255e.gif

  • 设置 kubelet 为开机自启动即可,由于没有生成配置文件,集群初始化后自动启动:
systemctl enable --now kubelet

1679282598385-c4d580b1-3880-460f-b02d-ac100f22b260.gif

4.3 查看 Kubernetes 安装所需镜像(可选)

  • 查看 Kubernetes 安装所需镜像:
kubeadm config images list

1679282605428-85fca16a-7ca3-4e36-9937-c1611d8a42e6.gif

4.4 下载 Kubernetes 安装所需镜像(可选)

  • 所有节点(三台机器)均需要如下的命令:
kubeadm config images pull --kubernetes-version=v1.25.7 \
--image-repository registry.aliyuncs.com/google_containers

1679282614628-c1daff20-025f-47b8-9964-fcf60ac8c82d.gif

  • 查看下载的镜像:
crictl images

注意:

  • containerd 的客户端工具有 ctr、crictl 和 nerdctl。
  • ctr 是由 containerd 提供的一个客户端工具。
  • crictl 是 CRI 兼容的容器运行时命令行接口,和 containerd 无关,由 Kubernetes 提供,可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序。
  • nerdctl 是和 Docker 兼容的 CLI 客户端,支持 Compose,默认没有安装,需要手动安装。

1679282622901-438d14a7-bc88-4f79-a164-14ba52470cee.gif

4.5 部署 Kubernetes 的 Master 节点

  • 在 192.168.68.20 机器上部署 Kubernetes 的 Master 节点:
kubeadm init \
  --apiserver-advertise-address=192.168.68.20 \
  --image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers \
  --kubernetes-version=v1.25.7 \
  --service-cidr=10.96.0.0/16 \
  --pod-network-cidr=10.244.0.0/16 \
  --token-ttl=0 # 如果不设置为 0 ,默认的 token 有效期是 24 小时

1679282633369-3790340c-c738-42d4-b488-271dcbf60c8e.gif

  • 日志信息如下:
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.68.20:6443 --token z4ugzv.txit41bi3yd30egp \
    --discovery-token-ca-cert-hash sha256:225cf235c1448cc41edc84747d2f7c9157d378bed66cc9fd3822450385ab5253
  • 根据日志信息提示操作,在 192.168.68.20 执行如下命令:
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

1679282643560-43158562-05cf-4a1e-bb40-0d64fb2685a4.gif

  • 默认的 token 有效期为 24 小时,当过期之后,该 token 就不能用了,这时可以使用如下的命令创建 token :
kubeadm token create --print-join-command
# 生成一个永不过期的 token
kubeadm token create --ttl 0 --print-join-command

4.6 部署 Kubernetes 的 Node节点

  • 根据日志提示操作,在 192.168.68.21 和 192.168.68.22 执行如下命令:
kubeadm join 192.168.68.20:6443 --token z4ugzv.txit41bi3yd30egp \
    --discovery-token-ca-cert-hash sha256:225cf235c1448cc41edc84747d2f7c9157d378bed66cc9fd3822450385ab5253

1679282649445-6d5808ff-fd26-4552-8a47-c0790a176c85.gif

4.7 部署网络插件

  • 配置 NetworManager 在有 NetworkManager 的系统上需要配置 NetworkManager 不接管 calico 的网卡:
cat <<EOF>> /etc/NetworkManager/conf.d/calico.conf
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico
EOF

1679282659250-034d1413-2ef0-4e46-aa91-7b8fc56a14ec.gif

  • Kubernetes 支持多种网络插件,比如 flannel、calico、canal 等,任选一种即可,本次选择 calico ,只需要在 k8s-master 节点安装即可。
kubectl apply -f https://projectcalico.docs.tigera.io/v3.25/manifests/calico.yaml

注意:Kubernetes 和 Calico 的版本对应关系,在这里

1679282666348-72c592d7-565c-4f7b-9ee9-711fe2f47cba.gif

  • 查看是否部署成功:
watch -n 1 kubectl get pod -A -o wide

1679282673852-f42e7b0e-04a7-413d-8448-a0b65d77c2c8.gif

  • 如果成功,将出现如下图所示的结果:

1679282705973-884dc490-1e91-469a-af41-a8f1cec43e61.png

4.9 Master 节点去污

  • 默认情况下,使用 kubeadm 安装 Kubernetes 集群的时候,Master 节点会带有污点,所以可以使用如下的命令进行去污:
kubectl get no -o yaml | grep taint -A 10
kubectl taint nodes --all node-role.kubernetes.io/control-plane-

4.10 测试

  • 使用 Nginx 来测试一下是否安装成功:
kubectl create deployment nginx --image=nginx:1.14-alpine
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get pods,svc

1679282712466-53204244-3789-4fa4-9671-9cdb0ae6c6b0.gif

更新: 2023-06-30 03:16:35
原文: https://www.yuque.com/fairy-era/yg511q/fhqtqd0v90smton2

Comments