整理 | 山河已无恙 校对 | 小雨青年
出品 | 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 endend
Step 2:执行vagrant命令。它将启动两个节点,一个主节点和一个工作节点。
vagrant up
Step 3 :登录主节点和工作节点安装集群初始化配置脚本。
vagrant ssh master
vagrant ssh worker0
main.sh
#!/bin/bashecho "[TASK 1] Disable and turn off SWAP"sed -i "/swap/d" /etc/fstabswapoff -aecho "[TASK 2] Stop and Disable firewall"systemctl disable --now ufw >/dev/null 2>&1echo "[TASK 3] Enable and Load Kernel modules"cat >>/etc/modules-load.d/containerd.conf<
Master node
vagrant@master:~$ vim main.shvagrant@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.shvagrant@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/bashecho "[TASK 1] Pull required containers"kubeadm config images pull >/dev/null 2>&1echo "[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/nullecho "[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>&1mkdir /home/vagrant/.kubecp /etc/kubernetes/admin.conf /home/vagrant/.kube/configchown -R vagrant:vagrant /home/vagrant/.kubeecho "[TASK 4] Generate and save cluster join command"kubeadm token create --print-join-command
vagrant@master:~$ vim master.shvagrant@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 commandkubeadm 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 wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEmaster Ready control-plane,master 2m41s v1.21.0 10.0.2.15
至此,我们已经解决了为什么Kubernetes不需要Docker来工作的问题,并且也看到了Docker在工作流程中的重要性,以及在没有Docker运行时的情况下安装Kubernetes是多么简单。
Kubernetes 正在成长,但改变不一定是痛苦的经历。
大多数用户不需要采取任何行动。对于那些需要的人来说,仍然有时间进行下一步的测试和计划。
聚焦云原生新技术、新实践,帮助开发者群体赢在开发范式转移的新时代。欢迎关注CSDN云原生微信公众号~
扫这里↓↓↓加入CSDN云原生交流群