各种关系
OCI 介绍
https://github.com/opencontainers/runtime-spec/blob/main/spec.md
Open Container Initiative Runtime Specification 指定容器的配置、执行环境和生命周期
因此执行的命令是 runc spec
OCI(Open Container Initiative,开放容器计划),是在 2015 年由 Docker、CoreOS 等公司共同成立的项目,并由 Linux 基金会进行管理,致力于 container runtime 标准的制定和 runc 的开发等工作。
所谓 container runtime,主要负责的是容器的生命周期的管理。OCI 主要分为容器运行时规范(runtime-spec) 和镜像规范(image-spec) 两部分,runtime-spec 标准对容器的创建、删除、查看、状态等操作进行了定义,image-spec 对镜像格式、打包(Bundle)、存储等进行了定义。
runc 介绍
runc,是由 Docker 贡献的对于 OCI 标准的一个参考实现,是一个可以用于创建和运行容器的 CLI(command-line interface) 工具。runc 直接与容器所依赖的 Cgroup/OS 等进行交互,负责为容器配置 Cgroup/namespace 等启动容器所需的环境,创建启动容器的相关进程。
为了兼容 OCI 标准,Docker 也做了架构调整。将容器运行时相关的程序从 Docker daemon 剥离出来,形成了containerd。containerd 向 Docker 提供运行容器的 API,二者通过 gRPC 进行交互。containerd 最后会通过 runc 来实际运行容器。
CRI 介绍
CRI(Container Runtime Interface,容器运行时接口)是 K8s 定义的一组与容器运行时进行交互的接口,用于将 K8s 平台与特定的容器实现解耦。在 K8s 早期的版本中,对于容器环境的支持是通过 Dockershim(hard code) 方式直接调用 Docker API 的,后来为了支持更多的容器运行时和更精简的容器运行时,K8s 在遵循 OCI 基础上提出了CRI。
总结
都是基础oci 规范, cri 是k8s 提的, containerd 是从docker daemon 分离出来的, 最后containerd 也是调用runc。


下载安装
https://github.com/opencontainers/runc/releases/tag/v1.0.3
安装了docker, 就有runc 了, 可能版本不一样;
下载runc.amd64, 然后改名字, 加执行权限;
放到/usr/bin 里;
准备工作
cd /opt/script; mkdir -p alpine/rootfs
docker pull alpine:3.12
docker export $(docker create alpine:3.12) | tar -C alpine/rootfs -xvf -
命令解析
在 Unix/Linux 中,"-" 通常表示标准输出或标准输入。在这个命令中,"-" 表示从标准输入中读取 tar 包的数据。
具体来说,tar -C alpine/rootfs -xvf - 命令中的 - 表示从标准输入中读取 tar 包的数据,而不是从文件中读取。这通常用于将 tar 包通过管道传递给另一个命令,或者从网络中获取 tar 包的数据。
在这个命令中,docker export 命令将容器中的文件系统导出为 tar 包,并将 tar 包的数据输出到标准输出中。然后,tar 命令通过 - 参数从标准输入中读取 tar 包的数据,并将数据解压到指定的目录中。
因此,在这个命令中,最后的 - 表示从标准输入中读取 tar 包的数据,这样就可以将 docker export 命令输出的 tar 包数据传递给 tar 命令进行解压。
OCI 规范
runc spec
总之,runc spec 命令是用于生成符合 OCI 标准的容器配置文件的工具,它可以帮助用户创建和管理符合标准的容器。
简单的说,OCI有两个规范,一个是容器运行时规范runtime-spec,一个是镜像格式规范image-spec。一个镜像,简单来说就是一个打包好的符合OCI规范的filesystem bundule。而bundule的话,前面介绍过,包含一个配置文件config.json和一个rootfs目录。
INFRA [root@wqdcsrv3160 alpine]# rc list
ID PID STATUS BUNDLE CREATED OWNER
abc 0 stopped /opt/script/runc/alpine 2023-06-01T06:33:22.403659746Z root
INFRA [root@wqdcsrv3160 alpine]# cd /opt/script/runc/alpine/
INFRA [root@wqdcsrv3160 alpine]# ll
total 5
-rw-r--r-- 1 root root 81 Jun 1 15:05 abc.out
-rw-r--r-- 1 root root 2811 Jun 1 14:33 config.json
drwxr-xr-x 20 root root 1024 Jun 1 14:21 rootfs
启动
rc run abc
ctrl + d 退出
-d 参数, --detach
有三个步骤
-
修改config.json
图片.png
图片.png golang 写个程序, 编译后放到/app 目录中, 设置可执行权限。
rc run -d abc > abc.out 2>&1
删除
rc kill abc
rc delete abc
挂载文件夹
"mounts": [
{
"destination": "/opt/script/runc/alpine/rootfs/app",
"source": "/opt/script/test",
"options": ["rbind","rw"]
},
destination 和 source 都必须是目录;
rc run -d abc > abc.out 2>&1 运行起来
rc exec -t abc sh 然后进去看一下。
虚拟网卡设置
结构:

yum install bridge-utils -y
brctl show
# 创建网桥
brctl addbr jtthink0
ip link set jtthink0 up
ip addr add 10.12.0.1/24 dev jtthink0
# 创建veth 设备对
ip link add name veth0-host type veth peer name veth0-ns
ip link set veth0-host up
brctl addif jtthink0 veth0-host
# 创建一个net namespace
ip netns add mycontainer
ip link set veth0-ns netns mycontainer
# 设置ns 里面的网卡名称和启动
ip netns exec mycontainer ip link set veth0-ns name eth0
ip netns exec mycontainer ip addr add 10.12.0.2/24 dev eth0
ip netns exec mycontainer ip link set eth0 up
ip netns exec mycontainer ip addr add 127.0.0.1 dev lo
ip netns exec mycontainer ip link set lo up
ip netns exec mycontainer ip route add default via 10.12.0.1
端口映射
修改config.json
"namespaces": [
{
"type": "pid"
},
{
"type": "network",
"path": "/var/run/netns/mycontainer"
},
{
"type": "ipc"
},
{
"type": "uts"
},
{
"type": "mount"
}
],
iptables -t nat -I PREROUTING -p tcp -m tcp --dport 9090 -j DNAT --to-destination 10.12.0.2:80
删除
iptables -t nat -D PREROUTING -p tcp -m tcp --dport 9090 -j DNAT --to-destination 10.12.0.2:80
还需要一些iptables 前置操作:
iptables -P FORWARD ACCEPT
vi /etc/sysctl.conf
# 找到下面的值并将0改成1
net.ipv4.ip_forward = 1
sysctl -p(使之立即生效)

