以上这幅图是docker创建容器,操作容器的过程,也是docker 的组成部分
containerd是docker的组成部分。 .sock文件是一份绑定unix域的socket创建时会生成的文件。你可以把这份文件想像成机器的端口 ,端口是远程两台机器内各自的进程相互通信时创建tcp/udp_socket需要绑定的,而你看到的这份.socket文件则是创建unix_socket需要绑定的 unix_socket可以让同一台机器的不同进程相互传输信息 就像tcp/udp_socket做的一样。区别是我们不再需要绑定端口。可以把端口让出来给其它需要的进程使用。下面给出一份unix域socket的使用代码
import socket as s
# 创建一个基于Unix域的socket
sock = s.socket(s.AF_UNIX)
# 绑定到指定路径
sock.bind('/tmp/somesocket')
# 开始监听该socket
sock.listen(1)
while True:
# 等待连接请求
connection, client_address = sock.accept()
print(connection,client_address)
# 接收数据
data = connection.recv(1024)
print(data.decode())
# 发送数据
connection.sendall(b'Hello, World!')
# 关闭连接
# connection.close()
import socket as s
# 创建一个基于Unix域的socket
client_sock = s.socket(s.AF_UNIX)
# 连接到服务器指定的路径
client_sock.connect('/tmp/somesocket')
# 发送数据
client_sock.sendall(b'Hello from client!')
# 接收数据
data = client_sock.recv(1024)
# 打印接收到的数据
print('Received', repr(data))
# 关闭连接
client_sock.close()
注意这行代码它位于第一份代码清单上,它将会在/tmp/路径下创建一份somesocket文件以作为两个不同的进程互相交流的接口文件,数据的中转都会通过它。如果你会网络编程你会发现创建tcp/udp代码的结构和它非常像。
现在了解了socket文件的工作原理。我们再看这行启动命令。
很明显docker的组成部分之一containerd会在/usr/bin/dockerd可执行程序运行后,对自己的监听服务创建并绑定在该.sock文件上,如果我们研究containerd监听这个“端口”后的执行代码 我们可以自己发送信息通过该.sock文件到containerd中并让程序正常执行,这就像我们自己写了一个docker client客户端一样。
接下来讨论一下runc他也是docker的组成部分之一.如果你查阅关于它的资料你会知道它是一个实现了oci规范的容器创建运行工具。我们对他不需要了解太对暂时知道当你给docker下达命令时最终执行拉取创建容器这等等基础工作的都是它runc.在安装完docker后我们就会拥有这份可执行程序。
就像这样你可以查看它的版本。以及你可以运行
runc -h
则可以查看他的使用说明。
接下来讨论cri-docker它的安装这里不过多讲述,你可以搜索并找到它的官网然后进入github仓库,直接选择对应的版本下载安装包。比如我的系统是ubuntu22.04,我找到jammy的deb包并且使用dpkg -i 安装它。
先对他的功能做个概述。首先看看为什么需要它。
k8s可以管理容器集群,这提供了对于容器化的微服务进程非常好的管理服务。早期k8s管理的容器底层是绑定docker的,但是你要知道容器的实现不只有docker还有其它的实现技术,而k8s则一直希望自己的代码可以兼容所有的容器,也就是说他不仅可以管理docker也可以管理其他的容器实现.
让我们想想有什么解决方案.方案一为每个容器的不同接口k8s自己实现代码并且当容器更新时根据它们的更新维护这些代码。嗯,这是个可行的方案但是太累了。方案二自己定义一个标准,k8s自己操作容器的代码接口不变,让那些想接入的容器实现自己适配k8s的接口标准。
不知道我这样说能对你有多少帮助。我们来看看k8s的工作流程。
这就是我们提到的方案2中的k8s接口标准。docker-ce的containerd并没有实现这套标准,
也就是说k8s发送的信息传入containerd的.sock文件containerd并不能处理。这个时候cri-docker的作用就体现了。
cri-dockerd的启动参数中有两个关键参数
--container-runtime-endpoint string The endpoint of backend runtime service. Currently unix socket and tcp endpoints are supported on Linux, while npipe and tcp endpoints are supported on windows. Examples:'unix:///var/run/cri-dockerd.sock', 'npipe:./pipe/cri-dockerd' (default "unix:///var/run/cri-dockerd.sock")
这个参数的默认值指向cri-docker启动后默认服务监听的.sock文件,注意它是属于cri-docker的,而cri-docker是实现了k8s的cri标准的也就是说把k8s传输数据到cri-docker的.sock,背后对应的服务代码是可以正常运行的。那么它的代码做了什么事呢。再来看这个参数
--docker-endpoint string Use this for the docker endpoint to communicate with. (default "unix:///var/run/docker.sock")
这个参数指向了docker的.sock文件。想要知道这份文件的作用可以跳转至https://blog.csdn.net/runner668/article/details/99870559
或搜索"关于/var/run/docker.sock"
这里简要概述一下,你可以使用这份.sock来与docker的守护进程containerd交互命令它拉取镜像等等功能,(当然最终还是会调用runc),使用这份文件和你使用docker client是一样的。
现在解释一下cri-docker做了什么,它接受k8s的请求并转达k8s的意思,使用docker containerd能明白的格式传输给containerd最终实现虽然docker无法接入k8s(如果我的资料没有差错的话docker的企业版好像是可以直接接入k8s的)但是通过一个中间件实现了k8s可以管理docker.
好了搭建k8s的前置知识到此就完成了,现在我们看看搭建的具体过程。
首先是前置工作准备一台虚拟机作为主节点,一台或多台虚拟机作为工作节点你可以使用vmware workstation完成创建虚拟机的工作,记得让它们和你的主机之间可以网络连通,可以连通外网
你可以在创建虚拟机的时候使用nat网络形式。
接下来准备ios镜像我这里使用的从huawei云下载下来的ubuntu22.04。在你的虚拟机上安装ubuntu
使用阿里云镜像的ubuntu22.04 apt源的配置步骤,配置你的虚拟机。使用aliyun镜像的容器镜像源的步骤安装docker-ce,
以上docker-ce安装步骤截图时间:2024/5/10 5:33
这里你会发现ubuntu的版本并没有标明有22.04,没有关系按照它的步骤做(至少我安装的时候是可以的)如果你实在担心可以尝试使用华为云的容器镜像,它也有安装docker的步骤。
你可以使用
docker info
我们需要让k8s的cgroupDriver和容器的cgroupDriver相同并且我们将使用kubeadm创建cluster而使用的版本大于1.22,并且我不打算设置k8s的cgroupDriver所以需要确保docker 的cgroupDriver也是systemd(我的系统的init进程是systemd)
从阿里下载的docker-ce已经是systemd,如果你是从华为云下载的话需要在/etc/docker/daemon.json文件中添加 "exec-opts": ["native.cgroupdriver=systemd"],
如果你不确定应该如何操作网上有很多资料告诉你应该如何更改cgroupDriver.
接下来按照官网以上这幅图进行操作
使用命令关闭swap 并且在/etc/fstab中给swap分区前加上#号确保每次启动swap不启用
确保每台节点互相连通,mac,uuid,端口开放在vmware的实验环境新建的虚拟机里这些并不用考虑,
我们需要修改使用hostnamectl hostname <str>命令修改各节点的主机名,并在/etc/hosts里添加所
有节点的路径解析。
安装cri-docker并且修改 ExecStart 添加
ExecStart=/usr/bin/cri-dockerd --pod-infra-container-image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.9 --container-runtime-endpoint fd://
不做这一步你会惊讶的发现之后的pull容器每次尝试pull pause:3.9时你都pull不下来,即使你在kubeadm中指定了镜像仓库,原因是cri-docker对这一参数有默认值。我们并不需要特意指定.sock文件的路径因为 如果你查看cri-docker的帮助它对于.sock的默认值缺省都是对的。
systemctl daemon-reload
systemctl restart cri-docker
接下来执行
kubeadm init --kubernetes-version=1.28.0 \ #注意自己的版本
--apiserver-advertise-address=192.168.2.180 \ #注意自己的主节点ip
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16 \
--ignore-preflight-errors=Swap \
--cri-socket=unix:///var/run/cri-dockerd.sock #这一步是把kubelet和cri-docker联系起来
kubeadm join 192.168.150.133:6443 --token ju1p1d.j7kb0y6khvivmzsg --discovery-token-ca-cert-hash sha256:dff8d443a88c16750ee9c3482d0946580713703e2a002378d9e3814367a302b4
--cri-socket=unix:///var/run/cri-dockerd.sock #注意从节点要加这一行