整理 | 山河已无恙 校对 | 小雨青年
出品 | CSDN云原生
声明:本文出自CNCF网站,最初由Alessandro Lo Manto在Sighup博客上发表。CSDN将文章翻译成中文,分享给大家。
2020年底,Kubernetes团队弃用了Docker,并宣布将在2021年底完全移除对Docker的支持。这种弃用带来了很多变化,因为使用Docker作为容器运行时接口(CRI)而不是开放容器倡议(OCI)造成了一点混乱。
那么,为什么要这么大惊小怪呢?我们应该继续写Dockerfile吗?
如今,人们仍然很难理解Docker是什么。公司、容器、镜像和开发者使用的工具之间似乎没有什么区别,对许多人来说,只有一个叫做“Docker”的词来指代这一切。
Docker是一个开发、发布和运行应用程序的开放平台。Docker能够将应用程序与基础设施分离,从而快速交付软件。Docker利用了Linux内核及其功能,因为独立运行进程,所以隔离方法十分重要。
Docker之所以使用Linux Container(LXC),是因为其使用Runtime 作为后端。随着任务的发展,LXC被改变为Containerd。
当前的Docker设置分为:Containerd(用于管理容器)和Dockerd(用于提供来自Docker主机的信息的持久进程守护进程)。被定义为“容器”的Docker,只不过是一个与用户友好的容器交互工具。它的创建方式使每个人都可以安装它、构建容器镜像、从注册表中提取镜像,并创建、启动和管理容器。这就是Docker被称为“容器”的原因。
那么Kubernetes是什么?和这一切又有什么关系?
要想理解为什么Kubernetes和Docker会一起出名,我们需要先了解Docker是如何集成在Kubernetes中以及开放容器倡议(OCI)和容器运行时接口(CRI)的含义。
Kubernetes采用容器的概念,它并不是在一台服务器上运行容器化应用程序,而是将它们分布在一个集群上。
容器的普及需要有一个开放的镜像标准。Docker Inc和CoreOS创建了OCI(Open Container Initiative,开放容器倡议),其使命是产生标准格式。它推出了两个具体的标准:
对二进制格式镜像的要求
一个描述如何交互和运行容器的规范。OCI维护着一个名为Runc的参考实现,Containerd在后台使用Runc与容器进行交互
OCI增加了不同容器运行时解决方案之间的互操作性,因此,镜像可以在任何其他遵守此标准的系统中运行。
为了工作,Kubernetes 需要一个支持CRI的容器运行时。CRI是一个Kubernetes API,它定义了Kubernetes与不同容器运行时交互的方式。因为它是标准化的规范,所以您可以选择想要使用的CRI实现或自行编写。
为什么Kubernetes不需要Docker作为容器运行时?Docker比Kubernetes更老,并且没有实现CRI,为什么它能够发挥作用?
Dockershim组件的创建是为了让你与CRI交互。但如今Docker有替代品,Kubernetes便不再需要保持这种额外的复杂性了。
前面解释过,Docker并不是一个容器运行时,它是一系列与容器交互的工具,只是一个中间人。
应该停止将Kubernetes与Docker一起使用吗?
如果您的集群已经由GKE、EKS或AKS(默认为Containerd)等主要云提供商配置,或者您只是一个Kubernetes用户,这对您没有影响。
Docker已经并将继续在Kubernetes生态系统中发挥重要作用。后者将继续运行Docker容器并从Docker注册表中提取镜像,因为Docker生成了符合OCI的镜像。
但是,让我们来谈谈自己吧!在本文中,我们将引导您使用Containerd而不是Docker创建一个Kubernetes集群。
下面我们编写一个基本的Vagrantfile和脚本配置供大家理解,可以按照以下提供的步骤创建Kubernetes集群。
作为先决条件,您需要安装和配置Virtualbox和Vagrant。
Step 1:在启动集群之前,首先在您选择的文件夹中创建一个Vagrantfile文件。
Vagrantfile
# -*- 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
Step 2:执行vagrant命令。它将启动两个节点,一个主节点和一个工作节点。
vagrant up
Step 3 :登录主节点和工作节点安装集群初始化配置脚本。
vagrant ssh master
vagrant ssh worker0
main.sh
#!/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<>/etc/sysctl.d/kubernetes.conf</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
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
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)
Step 4 :只在主节点上安装下面的脚本,并在最后复制kubeadm join命令。
master.sh
#!/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
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
Step 5 :复制并以sudo用户身份在工作节点中运行join命令。
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
Step 6 :在主节点上,列出所有集群节点,以确保工作节点连接到主节点并处于就绪状态。
kubectl get nodes -o wide
您可以使用Containerd而不是Docker来查看运行时。
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 Ubuntu 20.04.2 LTS 5.4.0-72-generic containerd://1.5.2
worker0 Ready 98s v1.21.0 10.0.2.15 Ubuntu 20.04.2 LTS 5.4.0-72-generic containerd://1.5.2
至此,我们已经解决了为什么Kubernetes不需要Docker来工作的问题,并且也看到了Docker在工作流程中的重要性,以及在没有Docker运行时的情况下安装Kubernetes是多么简单。
Kubernetes 正在成长,但改变不一定是痛苦的经历。
大多数用户不需要采取任何行动。对于那些需要的人来说,仍然有时间进行下一步的测试和计划。
聚焦云原生新技术、新实践,帮助开发者群体赢在开发范式转移的新时代。欢迎关注CSDN云原生微信公众号~
扫这里↓↓↓加入CSDN云原生交流群