Debian12 / Ubuntu24 上部署 Kubernetes(k8s) + docker

1,142 阅读11分钟

Debian12 / Ubuntu24 上部署 Kubernetes(k8s) + docker

由于ubuntu是基于Debian 的,所以这两个操作系统基本上差不太多。在下面的教程中,如果不显式标明debian 12系统或者ubuntu24系统,就默认这两个系统上的操作是一样的。

1. 机器列表

    节点名         操作系统
- k8s-master     Debian12  // K8S的master节点
- k8s-worker1    Debian12
- k8s-worker2    Ubuntu24
- k8s-worker3    Ubuntu24

2. 软件版本

  • docker 27.3.1 // 对docker的版本的要求好像不是很严格,我没查k8s和docker版本的依赖关系
  • cri-docker 最新版本
  • kubeadm 1.24.17
  • kubelet 1.24.17
  • kubectl 1.24.17

3. 基本步骤说明

  1. 系统准备工作 (所有服务器)

  2. 安装docker (所有服务器)

  3. 安装cri-dockerd (所有服务器)

  4. 安装 kubeadm, kubelet and kubectl (所有服务器)

  5. 配置集群 (master 和 worker 操作有区别)

4. 准备工作

4.1 更新系统,移除无用包 (我用的是比较新的系统,没有做这一步)

sudo apt update && sudo apt full-upgrade -y
sudo apt autoremove
sudo apt autoclean

如果更新了内核,重启。

4.2 关闭swap 分区

当内存不足时,linux会自动使用swap,将部分内存数据存放到磁盘中,这个这样会使性能下降,为了性能考虑推荐关掉。

暂时关闭:

sudo swapoff -a 

永久关闭:

然后编辑 /etc/fstab 文件,注释或删除 swap 那行(如有)。对于每个机器,可能会不同,但都是包含swap的行,前面加 # 注释掉即可。

对于Debian 12系统:

image.png

对于Ubuntu24系统:

image.png

4.3 开启网络转发等配置

  • overlay 是文件系统。由于Docker是分层的,上层的文件会覆盖下层的文件,使用到了overlay文件系统。
  • br_netfilter 网络转发。br_netfilter模块可以使 iptables 规则可以在 Linux Bridges 上面工作,用于将桥接的流量转发至iptables链。如果没有加载br_netfilter模块,那么并不会影响不同node上的pod之间的通信,但是会影响同node内的pod之间通过service来通信。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

# Apply sysctl params without reboot
sudo sysctl --system

4.4 配置时区

iswbm@master:~$ sudo timedatectl set-timezone Asia/Shanghai
iswbm@master:~$ date
Sat 15 Jan 2022 10:22:55 AM CST

4.5 关闭fire wall

这个我测试下来,两个操作系统都没有对应的,好像不设置也可以

5 安装docker

根据 kubernetes 官方文档,要安装官方版本的 docker,因此按照 docker 官方文档安装。

注意:这里直接用sudo apt install Debian或者 ubuntu仓库里的docker 软件是有问题的,后面会给出我遇到的问题。所以这里必须用官方的Docker

卸载非官方版本 Docker,因为会与官方版本冲突。

for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done

官方文档 安装

sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

启动Docker,设置开机启动

sudo systemctl enable docker --now

注意,官方 Docker 与 Debian 仓库里的 docker-compose 不同,官方 Docker 用 docker compose 来 compose,compose 作为一个插件,Debian 仓库中的 docker-compose 用 docker-compose 来 compose。这个区别,在k8s的部署中没有影响。

【可选】 docker 配置镜像源

如果你不确定要不要配置国内镜像源,可以试一下docker提供的hello-world容器

docker run hello-world

如果能正常下载hello-world镜像,并启动成功,就不需要配置国内镜像源。

配置国内镜像源的操作如下:

第一步:新建或编辑daemon.json
vim /etc/docker/daemon.json
 
第二步:daemon.json中编辑如下
{
    "registry-mirrors": ["http://hub-mirror.c.163.com"]
}
 
第三步:重启docker
systemctl restart docker.service
 
第四步:执行docker info查看是否修改成功
docker info

最近国内的镜像源都失效了,懂得都懂的原因。需要自己找一下能用的镜像源,替换上面的 "http://hub-mirror.c.163.com"

6 安装 cri-dockerd

cri-dockerd 是 Kubernetes 控制 Docker 的中间层。cri: container runtime interface

通俗点来说,k8s是通过cri-docker这个中间层,来控制docker的。

说明: 在k8s的老版本中,是默认用docker作为容器运行时的,k8s通过Dockershim中间层,来操作docker。Dockershim将在1.23版中从Kubelet中移除,这也移除了对Docker作为容器运行时的支持。k8s后来的版本中应该是默认使用containerd作为容器运行时的,所以在下面的安装过程中,我们需要指定使用docker作为容器运行时。

  1. 安装Golang。自行编译 cri-dockerd 需要 golang,如果提示找不到 go,安装 goalng: sudo apt install golang 我遇到的问题是apt仓库中go版本比较老,编译过程中提示版本不匹配,因此,这部分可以从官网下载需要的版本,自行安装。

这里我下载了go1.23.1.linux-amd64.tar.gz

tar zxvf go1.23.1.linux-amd64.tar.gz # 解压缩
sudo mv go /usr/local/               # 移动到需要的位置
sudo vim /etc/profile                # 配置环境变量

# 下面是在profile文件中增加的内容
export PATH=$PATH:/usr/local/go/bin

# 编辑后保存
source /etc/profile # 重新加载环境变量
which go            # 验证go路径是否是配置的路径
  1. 编译cri-dockerd
git clone https://github.com/Mirantis/cri-dockerd.git
cd cri-dockerd
make cri-dockerd
sudo mkdir -p /usr/local/bin
sudo install -o root -g root -m 0755 cri-dockerd /usr/local/bin/cri-dockerd
sudo install packaging/systemd/* /etc/systemd/system
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service
sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket
  1. 确认cri-dockerd安装成功
sudo ls /var/run/cri-docker.socket # 如果这个文件存在说明安装正常
sudo systemctl status cri-docker   # 如果状态显示activate 说明正常

image.png

7 安装 kubeadm, kubelet and kubectl

sudo apt-get update
sudo apt-get install -y apt-transport-https
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl # 关闭这三个程序的自动更新

至此,Kubeadm 安装完成

【可选】 如果packages.cloud.google.com 这个地址访问不了,可以用下面的国内源

# 安装基础软件并设置源
iswbm@master:~$ sudo apt-get install -y ca-certificates curl software-properties-common apt-transport-https curl
iswbm@master:~$ curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
iswbm@master:~$ sudo tee /etc/apt/sources.list.d/kubernetes.list <<EOF
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF

# 刷新软件列表,然后直接安装
iswbm@master:~$ sudo apt-get update
iswbm@master:~$ sudo apt-get install -y kubelet kubeadm kubectl

# 阻止自动更新(apt upgrade时忽略)。所以更新的时候先unhold,更新完再hold。
iswbm@master:~$ sudo apt-mark hold kubelet kubeadm kubectl

【可选】 如果需要安装特定版本的软件,可以用如下命令:

sudo apt-cache madison kubelet # 查看可用版本
sudo apt-cache madison kubeadm # 查看可用版本
sudo apt-cache madison kubectl # 查看可用版本
sudo apt-get install -y kubelet=1.24.17-00 kubeadm=1.24.17-00 kubectl=1.24.17-00

8 配置集群

官方文档 配置集群。

一个很重要的问题是网络,k8s 集群中有很多台计算机,但是对外只有一个网络接口,比如你在 k8s 上运行一个网站,那么只能通过一个 ip 地址访问这个网站,但是集群中的每一台计算机都需要一个 ip 地址来通信,这个地址可以是私有地址,也可以是公网地址。k8s 本身不提供网络解决方案,需要安装插件官方文档:installing addons

这里选用了 www.tigera.io/project-cal…,不同插件操作方法略有不同。

8.1 master节点

8.1.1 初始化
  1. 初始化:
sudo kubeadm init --pod-network-cidr 172.16.0.0/16 \
    --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers \
    --apiserver-bind-port 6443 \
    --cri-socket unix:///var/run/cri-dockerd.sock # 指定运行时,是cri-dockerd

如果一切正常,会得到下面这样的输出。

image.png

记下输出中的 kubeadm join 命令,接下来添加工作节点需要 Token,每个 Token 默认 24 小时后过期

Token 过期或者忘记,可以使用 kubeadm token create --print-join-command 直接生成一个新的。

根据提示,下一步操作。

  1. 配置kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
8.1.2 安装Calico 网络插件

目前版本 3.26.1,请到官网找最新版本 docs.tigera.io/calico/late…

1. 下载配置文件

为更好的管理yaml文件,建议在系统中创建专属文件夹对yaml文件进行管理,本实例将所有yaml放置在/home/kube/yaml下;

#创建yaml文件管理路径 
mkdir -p /home/kube/yaml

下载Calico配置文件“calico.yaml”,本次部署calico-3.26版本,请根据实际需求进行下载,(建议不低于v3.28这个版本)并在K8s管理的master主节点中执行

#下载calico的部署官方文件
cd /home/kube/yaml && wget  --no-check-certificate  https://projectcalico.docs.tigera.io/archive/v3.25/manifests/calico.yaml
#以下为执行结果显示内容
--2024-07-10 17:22:47--  https://projectcalico.docs.tigera.io/archive/v3.28/manifests/calico.yaml
Resolving projectcalico.docs.tigera.io (projectcalico.docs.tigera.io)... 46.137.195.11, 13.215.144.61, 2406:da18:880:3801::c8, ...
Connecting to projectcalico.docs.tigera.io (projectcalico.docs.tigera.io)|46.137.195.11|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 238089 (233K) [text/yaml]
Saving to: ‘calico.yaml’
100%[==============================================================================>] 238,089      438KB/s   in 0.5s   
2024-07-10 17:22:48 (438 KB/s) - ‘calico.yaml’ saved [238089/238089]

2. 修改calico.yaml如下内容

执行ip addr 查看k8s的master节点的服务网卡名称

#查看当前服务器的网卡信息 
ip addr
vim calico.yaml

使用vim打开calico.yaml文件,找到如下内容,在其下方添加如下内容 原配置(大概在calico.yaml文件的第4567行)

- name: CLUSTER_TYPE
  value: "k8s,bgp"

新配置:

# CLUSTER_TYPE 下方添加信息
- name: CLUSTER_TYPE
  value: "k8s,bgp" 
# 下方为新增内容 
- name: IP_AUTODETECTION_METHOD 
  value: "interface=eno2"

需要注意的是:,这里IP_AUTODETECTION_METHOD是辅助calico去选择网卡,上述的例子里,ens33是使用的网卡名。不同服务器,可能不同。此外需要注意的是calico会被部署到所有的k8s节点上,因此,需要考虑所有节点的情况。

我这里,有两台服务器是eno2,另外两台是vmbr0,配置就可以用正则表达式写:

- name: IP_AUTODETECTION_METHOD 
  value: "interface=eno2|vmbr0"

3. 部署插件

kubectl apply -f calico.yaml

默认情况下,出于安全的考虑,不能在主节点上跑 pod。

至此,主节点就设置好了,查看状态。

kubectl get node  # 应该能看到当前master服务器节点
kubectl get pod
kubectl get pods --all-namespaces

8.2 设置 worker节点

worker节点上使用 kubeadm join 命令,执行

sudo kubeadm join k8s-master:6443 --token sluqvx.itdsjivbewuiinfx \
        --discovery-token-ca-cert-hash sha256:95669c834aa9e861aed6a08783d1f893223ec327ad2612aba016c2b457afb2345 \
        --cri-socket unix:///var/run/cri-dockerd.sock

注意: 上面这个命令是从master 节点,执行完kubeadm init 后提示的,直接拷贝过来执行就可以。

安装完毕后到master上,查看节点状态。如果显示都是ready,说明安装成功。

image.png

报错和解决方法

1. kubeadm init 报错

Unfortunately, an error has occurred:

timed out waiting for the condition

This error is likely caused by:

- The kubelet is not running

- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:

- 'systemctl status kubelet'

- 'journalctl -xeu kubelet'

Additionally, a control plane component may have crashed or exited when started by the container runtime.

To troubleshoot, list all containers using your preferred container runtimes CLI.

Here is one example how you may list all running Kubernetes containers by using crictl:

- 'crictl --runtime-endpoint unix:///var/run/cri-dockerd.sock ps -a | grep kube | grep -v pause'

Once you have found the failing container, you can inspect its logs with:

- 'crictl --runtime-endpoint unix:///var/run/cri-dockerd.sock logs CONTAINERID'

这种情况,报的错误一般都不是特别明显,需要仔细甄别。例如这里的提示,就不是kubelet启动不了的原因:

- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

通过如下的命令查看启动不了的原因

sudo systemctl status kubelet

sudo journalctl -xeu kubelet

我这里遇到的问题是有些镜像下载不下来。使用下面的方法解决了

2. 镜像下载不下来

master 节点

kubeadm config images list

# 查询kubeadm 需要的docker镜像
kubeadm config images list

# 查询结果
registry.k8s.io/kube-apiserver:v1.24.17
registry.k8s.io/kube-controller-manager:v1.24.17
registry.k8s.io/kube-scheduler:v1.24.17
registry.k8s.io/kube-proxy:v1.24.17
registry.k8s.io/pause:3.7
registry.k8s.io/etcd:3.5.6-0
registry.k8s.io/coredns/coredns:v1.8.6

手动拉取镜像

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.24.17
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.24.17
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.24.17
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.24.17
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0
docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.6

重命名镜像

docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.24.17 registry.k8s.io/kube-apiserver:v1.24.17
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.24.17 registry.k8s.io/kube-controller-manager:v1.24.17
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.24.17 registry.k8s.io/kube-scheduler:v1.24.17
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.24.17 registry.k8s.io/kube-proxy:v1.24.17
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.7 registry.k8s.io/pause:3.7
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.6-0 registry.k8s.io/etcd:3.5.6-0
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.6 registry.k8s.io/coredns/coredns:v1.8.6

其他镜像 kubeadm config images list 没有列出下面的镜像,我是从报错信息中看到的。

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 registry.k8s.io/pause:3.9
worker节点

worker 节点只需要下载下面这一个镜像,不需要coredns等。

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9
docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 registry.k8s.io/pause:3.9

3. 清除kubeadm之前的安装和配置

如果kubeadm init执行过一次,再次执行的话,会报错。需要重置。

sudo kubeadm reset

由于我们使用了docker作为运行时,需要命令行中,增加运行时配置信息。

sudo kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock

4. docker和cri-dockerd状态和重启

查看状态,如果状态不正常,有些情况可能重启就好了。

sudo systemctl status docker
sudo systemctl status cri-docker
sudo systemctl status kubelet

重启对应服务

sudo systemctl restart docker
sudo systemctl restart cri-docker
sudo systemctl restart kubelet

5. /proc/sys/net/bridge/bridge-nf-call-iptables does not exist

这个错误通常发生在尝试配置Kubernetes网络模式为bridge时,系统无法找到/proc/sys/net/bridge/bridge-nf-call-iptables文件。这个文件负责确定是否应该通过br_netfilter模块使桥接流量流经iptables规则。

解决方法: 确保你的系统已经加载了br_netfilter模块。可以通过运行以下命令来加载:

sudo modprobe br_netfilter

如果模块已经加载,但文件仍然不存在,你可能需要手动创建它。可以通过以下命令创建一个值为1的文件:

echo '1' | sudo tee /proc/sys/net/bridge/bridge-nf-call-iptables

6. 删除节点,重新添加

有些情况下,你可能需要删除worker重新添加。

在主节点删除 worker node:

kubectl drain [node name] --ignore-daemonsets
kubectl delete node [node name]

在worker节点reset

sudo kubeadm reset --cri-socket unix:///var/run/cri-dockerd.sock
sudo kubeadm join k8s-master:6443 --token sluqvx.itdsjivbewuiinfx \ 
--discovery-token-ca-cert-hash sha256:95669c834aa9e861aed6a08783d1f893223ec327ad2612aba016c2b457afb2345 \ 
--cri-socket unix:///var/run/cri-dockerd.sock

注意 --cri-socket unix:///var/run/cri-dockerd.sock 可能需要你自己加上

7. crictl 配置运行时

crictl 命令有几个子命令和运行时参数。 有关详细信息,请使用 crictl help 或 crictl <subcommand> help 获取帮助信息。

你可以用以下方法之一来为 crictl 设置端点:

  • 设置参数 --runtime-endpoint 和 --image-endpoint
  • 设置环境变量 CONTAINER_RUNTIME_ENDPOINT 和 IMAGE_SERVICE_ENDPOINT
  • 在配置文件 --config=/etc/crictl.yaml 中设置端点。 要设置不同的文件,可以在运行 crictl 时使用 --config=PATH_TO_FILE 标志。
说明:

如果你不设置端点,crictl 将尝试连接到已知端点的列表,这可能会影响性能。

你还可以在连接到服务器并启用或禁用调试时指定超时值,方法是在配置文件中指定 timeout 或 debug 值,或者使用 --timeout 和 --debug 命令行参数。

要查看或编辑当前配置,请查看或编辑 /etc/crictl.yaml 的内容。 例如,使用 containerd 容器运行时的配置会类似于这样:

runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: unix:///var/run/containerd/containerd.sock
timeout: 10
debug: true

参考文章列表