【翻译】如何在没有Docker的情况下运行Kubernetes

kubernetes在 v1.20 版本时宣布将弃用 docker,在 2021 年下半年发布的 v1.23 版本中,彻底移除 dockershim 代码,意味着那时 kubernetes 支持的容器运行时不再包括 docker,使用 containerd 作为 runtime,那么,在没有Docker的情况下,我们怎么去管理应用Kubernetes?

如何在没有Docker的情况下运行Kubernetes

声明:本文原文来自CNCF官方博客。由山河已无恙将文章翻译成中文,分享给大家。

亚历山德罗·洛·曼托 于2022年1月19日发布于CNCF

本文最初由 亚历山德罗·洛·曼托 发表于Sighup

在2020年底,Kubernetes团队弃用了Docker,并宣布将在2021年底完全移除对Docker的支持。这种弃用带来了多个变化,因为使用Docker作为CRI 而不是Docker作为OCI 而造成了一点混乱。

那么,为什么要这么大惊小怪呢?我们应该继续写Dockerfile吗?

在当今世界,人们仍然很难理解Docker是什么。公司、容器、镜像和开发者使用的工具之间似乎没有什么区别。到目前为止,对许多人来说,只有一个词叫做DOCKER来指代这一切。

Docker内部的奥秘

Docker是一个开发、发布和运行应用程序的开放平台。Docker使您能够将应用程序与基础设施分离,从而可以快速交付软件。

Docker概述信息见Docker官方文档

Docker利用了Linux内核及其功能。隔离方法是很重要的,因为它们是独立运行进程的。

Docker之所以使用Linux container (LXC)是因为使用Runtime 作为后端。随着任务的发展,LXC被改为containerd。

当前的Docker设置分为:containerd(用于管理容器)和dockerd(用于提供来自Docker主机的信息的持久进程守护进程)。

Docker架构

Docker被定义为一个“容器”,不过是一个用户友好的与容器交互的工具。它的创建方式使每个人都可以安装它、构建容器镜像、从注册表中提取镜像以及创建、启动和管理容器。这就是为什么Docker被称为“容器”的原因。

那么Kubernetes是什么?这和这一切又有什么关系?

‌为了了解 Kubernetes 和 Docker 为何一起出名,让我们了解 Docker 是如何集成到 Kubernetes 中的,以及开放容器倡议 (OCI) 和容器运行时接口 (CRI) 的含义。

什么是 OCI?

Kubernetes 采用容器的概念,而不是在一台服务器上运行容器化应用程序,而是将它们分布在集群中。

由于容器的流行,需要一个开放的镜像标准。Docker Inc 和 CoreOS 创建了Open Container Initiative

  • 对二进制格式镜像的要求。
  • 描述如何交互和运行容器的规范。OCI 维护一个名为runc的参考实现,并且 containerd 在后台使用 runc 与容器交互。

OCI 增加了不同容器运行时解决方案之间的互操作性。因此,镜像可以在任何其他遵守此标准的系统中运行。

OCI运营案例

什么是 CRI?

为了工作,Kubernetes 需要一个支持 CRI 的容器运行时。

CRI 是一个 Kubernetes API,它定义了 Kubernetes 与不同容器运行时交互的方式。因为它在规范中是标准化的,所以您可以选择要使用的 CRI 实现或编写自己的实现。

kubelet 的工作原理

为什么 Kubernetes 不需要 Docker 作为容器运行时?

Docker 比 Kubernetes 更老,并且没有实现 CRI,为什么它可以工作?

Dockershim 组件的创建允许与 CRI 交互。但是今天,Docker 有替代品,Kubernetes 不再需要保持这种额外的复杂性

使用上面解释的架构,Docker 不是容器运行时,正如我们上面已经说过的,它是一系列与容器交互的工具,只是一个中间人。

Dockershim 与 containerd

我应该停止将 Kubernetes 与 Docker 一起使用吗?‌

如果您的集群已经由 GKE、EKS 或 AKS‌(默认为 containerd)等主要云提供商配置,或者您只是 Kubernetes 用户,这对您没有影响。

Docker 已经并将继续在 Kubernetes 生态系统中发挥重要作用。后者将继续运行我们的 Docker 容器并从 Docker 注册表中提取镜像,因为 Docker 会生成符合 OCI 的镜像。

但是,但让我们回到我们自己的身边吧!在本文中,我们将引导您使用 containerd 而不是 Docker 创建 Kubernetes 集群。‌

Vagrant VM 上的集群设置

下面我们编写了一个基本的 Vagrantfile 和脚本配置供任何人理解。按照提供的步骤创建 Kubernetes 集群。

作为先决条件,您需要安装和配置Virtualbox和Vagrant

第 1 步:在启动集群之前,首先在您选择的文件夹中创建一个Vagrantfile 文件。

Vagrantfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# -*- mode: ruby -*-
# vi: set ft=ruby :

ENV['VAGRANT_NO_PARALLEL'] = 'yes'

Vagrant.configure(2) do |config|

# Kubernetes Master Server
config.vm.define "master" do |node|

node.vm.box = "generic/ubuntu2004"
node.vm.box_check_update = false
node.vm.box_version = "3.2.18"
node.vm.hostname = "master"

node.vm.network "private_network", ip: "172.0.0.100"

node.vm.provider :virtualbox do |v|
v.name = "master"
v.memory = 2048
v.cpus = 2
end

node.vm.provider :libvirt do |v|
v.memory = 2048
v.nested = true
v.cpus = 2
end


end

# Kubernetes Worker Node

config.vm.define "worker0" do |node|

node.vm.box = "generic/ubuntu2004"
node.vm.box_check_update = false
node.vm.box_version = "3.2.18"
node.vm.hostname = "worker0"

node.vm.network "private_network", ip: "172.0.1.101"

node.vm.provider :virtualbox do |v|
v.name = "worker0"
v.memory = 1024
v.cpus = 1
end

node.vm.provider :libvirt do |v|
v.memory = 1024
v.nested = true
v.cpus = 1
end

end

end

第 2 步 :执行 vagrant 命令。它将启动两个节点,一个主节点和一个工作节点。

vagrant up

第 3 步 :登录主节点和工作节点安装集群初始化配置脚本。

vagrant ssh master

vagrant ssh worker0

main.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/bin/bash

echo "[TASK 1] Disable and turn off SWAP"
sed -i '/swap/d' /etc/fstab
swapoff -a

echo "[TASK 2] Stop and Disable firewall"
systemctl disable --now ufw >/dev/null 2>&1

echo "[TASK 3] Enable and Load Kernel modules"
cat >>/etc/modules-load.d/containerd.conf<<EOF
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter

echo "[TASK 4] Add Kernel settings"
cat >>/etc/sysctl.d/kubernetes.conf<<EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system >/dev/null 2>&1

echo "[TASK 5] Install containerd runtime"
apt update -qq >/dev/null 2>&1
apt install -qq -y containerd apt-transport-https >/dev/null 2>&1
mkdir /etc/containerd
containerd config default > /etc/containerd/config.toml
systemctl restart containerd
systemctl enable containerd >/dev/null 2>&1

echo "[TASK 6] Add apt repo for kubernetes"
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - >/dev/null 2>&1
apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main" >/dev/null 2>&1

echo "[TASK 7] Install Kubernetes components (kubeadm, kubelet and kubectl)"
apt install -qq -y kubeadm=1.21.0-00 kubelet=1.21.0-00 kubectl=1.21.0-00 >/dev/null 2>&1

Master node

1
2
3
4
5
6
7
8
9
vagrant@master:~$ vim main.sh
vagrant@master:~$ sudo bash main.sh
[TASK 1] Disable and turn off SWAP
[TASK 2] Stop and Disable firewall
[TASK 3] Enable and Load Kernel modules
[TASK 4] Add Kernel settings
[TASK 5] Install containerd runtime
[TASK 6] Add apt repo for kubernetes
[TASK 7] Install Kubernetes components (kubeadm, kubelet and kubectl)

Worker node

1
2
3
4
5
6
7
8
9
vagrant@worker0:~$ vim main.sh
vagrant@worker0:~$ sudo bash main.sh
[TASK 1] Disable and turn off SWAP
[TASK 2] Stop and Disable firewall
[TASK 3] Enable and Load Kernel modules
[TASK 4] Add Kernel settings
[TASK 5] Install containerd runtime
[TASK 6] Add apt repo for kubernetes
[TASK 7] Install Kubernetes components (kubeadm, kubelet and kubectl)

第 4 步 :我只在主节点上安装下面的脚本,并在最后复制kubeadm join 命令。
master.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

echo "[TASK 1] Pull required containers"
kubeadm config images pull >/dev/null 2>&1

echo "[TASK 2] Initialize Kubernetes Cluster"
kubeadm init --apiserver-advertise-address=172.0.0.100 --pod-network-cidr=192.168.0.0/16 >> /root/kubeinit.log 2>/dev/null

echo "[TASK 3] Deploy Calico network"
kubectl --kubeconfig=/etc/kubernetes/admin.conf create -f https://docs.projectcalico.org/v3.18/manifests/calico.yaml >/dev/null 2>&1
mkdir /home/vagrant/.kube
cp /etc/kubernetes/admin.conf /home/vagrant/.kube/config
chown -R vagrant:vagrant /home/vagrant/.kube

echo "[TASK 4] Generate and save cluster join command"
kubeadm token create --print-join-command
1
2
3
4
5
6
7
8
9
vagrant@master:~$ vim master.sh
vagrant@master:~$ sudo bash master.sh

[TASK 1] Pull required containers
[TASK 2] Initialize Kubernetes Cluster
[TASK 3] Deploy Calico network
[TASK 4] Generate and save cluster join command

kubeadm join 172.0.0.100:6443 --token 5d6fgz.0lll5srvyxa9wfcm --discovery-token-ca-cert-hash sha256:0828fbc966896ac32550a7641d54593ef98738d2878ed80c1966431888cc1324

第 5 步 :复制并以sudo用户身份在工作节点中运行 join 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vagrant@worker0:~$ sudo kubeadm join 172.0.0.100:6443 --token 5d6fgz.0lll5srvyxa9wfcm --discovery-token-ca-cert-hash sha256:0828fbc966896ac32550a7641d54593ef98738d2878ed80c1966431888cc1324
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster

步骤 6 :在主节点上,列出所有集群节点,以确保工作节点连接到主节点并处于就绪状态。

kubectl get nodes -o wide

您可以使用containerd而不是Docker来查看运行时 :)

1
2
3
4
vagrant@master:~$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master Ready control-plane,master 2m41s v1.21.0 10.0.2.15 <none> Ubuntu 20.04.2 LTS 5.4.0-72-generic containerd://1.5.2
worker0 Ready <none> 98s v1.21.0 10.0.2.15 <none> Ubuntu 20.04.2 LTS 5.4.0-72-generic containerd://1.5.2

结论‌‌

我们已经解决了为什么 Kubernetes 不需要 Docker 来工作,并且我们已经看到了 Docker 在工作流中的重要性以及在没有 Docker 运行时的情况下安装 Kubernetes 是多么简单。

在 1.20 版中,您将收到 Docker 的弃用警告。1.23 版肯定会删除此功能,并且一开始肯定会引起一些问题。但这不会是灾难性的,随着技术的发展,好处将会显现。

Kubernetes 正在成长,但改变不一定是痛苦的经历。

大多数用户不需要采取任何行动。对于那些这样做的人,仍有时间进行测试和计划。


参考:

发布于

2022-04-12

更新于

2023-06-21

许可协议

评论
Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×