nerdctl 网络
创建流程
- 创建 CNI 配置文件
- 创建 resolv.conf 文件
- 创建 hosts 文件
- 创建 hostname 文件
- 触发 oci createRuntime hook
- 调用 nerdctl internal oci-hook createRuntime
- 创建 hostsstore
- 加载 CNI 插件配置。设置 CNI 插件的可执行文件目录
- 调用 cni.New 设置 CNI 配置,遵循 CNI 配置标准
- 调用 cni.Setup。遵循 CNI 的执行标准
- 直接在
/proc/<容器 pid>/ns/net
路径创建 network namespace - 执行 attachNetworks,根据 CNI 配置调用 CNI 插件
- ipam - host-local 插件 会分配动态 IP 给容器网络
- 把 CNI 插件的返回 JSON 格式重新整理,返回给上层
- 直接在
- 调用 hostsstore.Acquire,把新创建的容器网络配置信息(即 cni.Setup 的返回值)写入到 meta.json
- 调用 hostsstore 读取 meta.json 的内容配置,更新到 hosts 文件
- 调用 nerdctl internal oci-hook createRuntime
- 容器网络创建完成
所以 containerd 不负责容器网络的创建,这都是由 nerdctl 直接控制的。
CNI 配置
CNI 就两个相关配置,插件可执行文件和插件配置文件。这两类文件的搜索路径在 containerd config.toml 中设置。
- CNI 插件可执行文件
- 目录在 config.toml 中
[plugins."io.containerd.grpc.v1.cri".cni]
的bin_dir
路径。通常是/etc/cni/net.d
- 可执行文件通常是第三方 CNI 项目提供的,下载可执行文件放到这个目录即可。
- 目录在 config.toml 中
- CNI 插件配置
- 目录在 config.toml 中
[plugins."io.containerd.grpc.v1.cri".cni]
的conf_dir
路径。通常是/usr/lib/cni
- 插件的配置文件通常是以 .conflist(或 .conf 或 .json)文件名结尾的文件。
- 目录在 config.toml 中
CNI 插件
调用插件是通过环境变量和配置文件传递给插件,配置内容通过 stdin 输入,插件把 JSON 输出到 stdout 来返回结果。
resolv.conf
resolv.conf 文件路径是 <dataStore>/containers/<NS>/<ID>/resolv.conf
。 它的内容由三部分组成:
- 宿主机的 /etc/resolv.conf
- slirp4Dns 的配置
- nerdctl –dns 的配置
举个例子,resolv.conf 的内容:
$ cat /var/lib/nerdctl/1935db59/containers/default/3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5/resolv.conf
search HAN
nameserver 192.168.1.2
这个文件在创建容器时会被 mount –bind 到容器的 /etc/resolv.conf。
hosts
hosts 文件路径是 <dataStore>/etchosts/<NS>/<ID>/hosts
。
这个文件在创建容器时会被 mount –bind 到容器的 /etc/hosts。
hostname
hostname 文件路径是 <dataStore>/containers/<NS>/<ID>/hostname
。
这个文件在创建容器时会被 mount –bind 到容器的 /etc/hostname。
meta.json
meta.json 文件路径是 <dataStore>/etchosts/<NS>/<ID>/meta.json
NS 是 containerd namespace 的名称。如果调用 containerd 的上游是 Docker 默认为 moby
,Kubernetes 默认为 k8s.io
,其他默认为 default
。
ID 是容器 ID。
<dataStore>/etchosts/<NS>/<ID>/
在容器启动前创建,在容器删除后删除,容器 stop 时依然保留。
举个例子,我创建了一个 k3s 容器。其容器 ID 是 3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5
。
$ ls /var/lib/nerdctl/1935db59/etchosts/default/
21b5486e0cedfb4560d9873c1d57c368fbee8252b5ca58147d53b37190d9c578 7fdc35f51709ccbe8f5e84a7dbaf56edb8b7ff9f4644b05fa3e7dd873c4dd0c9
39a65e7482273a1f569ac2397dd4af10a651b5e577f96c0b6e230ed43952db10 846347fb07a6306da611c53136ffec09d04035de2752617976b0ed27b3004ac5
3a508a0b1d9f5f793feb0ff4439fd2fca7f5200bb36283fc13ed093365332d23 874b83075c1c2195e4fcff38dcde77d150411e9d667c43ab776175b041b0304a
3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5 927b7fe40db96b7dcfe2955e86922397c407a9956565318ccd527c65d1d2825a
45d2d2d3aba769029bcf55821142a2c0723537436d038b5387305cae2c5116a3 d5b993c9a7e00d182f85f5ba97c331cb6ee99dd75c8f82a7f6b11bbf50ea2018
78ee76c2653b708c3c11c31b91e1fe6ef49268432978f56c5c0f0f257ceb3099
$ ls /var/lib/nerdctl/1935db59/etchosts/default/3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5/
hosts meta.json
$ cat /var/lib/nerdctl/1935db59/etchosts/default/3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5/hosts
# <nerdctl>
127.0.0.1 localhost localhost.localdomain
:1 localhost localhost.localdomain
10.4.10.15 server server.k3s_default k3s_server_1 k3s_server_1.k3s_default
# </nerdctl>
$ python3 -m json.tool /var/lib/nerdctl/1935db59/etchosts/default/3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5/meta.json
{
"Namespace": "default",
"ID": "3c41e9ff441d6282bed1d170c3d4abde79e563a17c658b23f75501662cff5bf5",
"Networks": {
"k3s_default": {
"cniVersion": "1.0.0",
"interfaces": [
{
"name": "nerdctl1",
"mac": "86:58:72:24:a2:e4"
},
{
"name": "veth2c83f02c",
"mac": "4a:d1:11:ec:89:a1"
},
{
"name": "eth0",
"mac": "72:d8:24:77:1c:51",
"sandbox": "/proc/1065816/ns/net"
}
],
"ips": [
{
"interface": 2,
"address": "10.4.10.15/24",
"gateway": "10.4.10.1"
}
],
"routes": [
{
"dst": "0.0.0.0/0"
}
],
"dns": {}
}
},
"Hostname": "server",
"ExtraHosts": {},
"Name": "k3s_server_1"
}
ipam 插件
- dhcp : Runs a daemon on the host to make DHCP requests on behalf of a container
- host-local : Maintains a local database of allocated IPs
- static : Allocates static IPv4/IPv6 addresses to containers
https://www.cni.dev/plugins/current/ipam/
host-local 插件会把分配的 IP 信息放到 /var/lib/cni/networks/$NETWORK_NAME
下, 可以修改 dataDir
配置来改变存放路径。