一、版本信息

内核版本:5.19.12-1.el7.elrepo.x86_64

系统版本:CentOS Linux release 7.9.2009

二、下载文件: 

wget https://github.com/opencontainers/runc/releases/download/v1.1.4/runc.amd64
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.25.0/crictl-v1.25.0-linux-amd64.tar.gz
wget https://github.com/containerd/containerd/releases/download/v1.6.8/containerd-1.6.8-linux-amd64.tar.gz

上面下载的文件说明

runc.amd64:cri-containerd-cni-1.6.8-linux-amd64.tar.gz 包中包含的 runc 在 CentOS 7 下的动态链接有问题,这里需要从 runc 的 github 上单独下载 runc,并替换安装 containerd 后中的 runc

containerd-1.6.8-linux-amd64.tar.gz:包含containerd和它的containerd-shim以及命令行工具ctr

crictl-v1.25.0-linux-amd64.tar.gz:包含CRI的命令行工具crictl

三、添加相关的模块

1、运行docker时,出现以下信息,我们需要修改存储驱动的默认文件系统

crictl下载的镜像在哪里_kubernetes

问题原因:

centos系统docker默认使用存储驱动是devicemapper,而这种存储驱动有两种模式loop-lvm和direct-lvm,不巧默认又使用了比较低效的loop-lvm

解决方案一:使用direct-lvm,配置方式网上很多 ,百度一下就行了
解决方案二:使用overlay文件系统,因为这个方案比较简单,
配置步骤如下:
# 添加自开启自动加载模块
cat << EOF > /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

# 如果 containerd 已经运行着,需要删除永久存储的数据
# rm -rf /var/lib/containerd/
另外提示:docker需要修改这个配置
# 如果 docker 已经运行着,需要删除永久存储的数据
# rm -rf /var/lib/docker

vim /usr/lib/systemd/system/docker.service
# ExecStart=/usr/bin/dockerd
ExecStart=/usr/bin/dockerd --storage-driver=overlay -g /opt/docker

2、br_netfilter 模块用于将桥接流量转发至 iptables 链,br_netfilter 内核参数需要开启转发,如果不部署k8s的话,可以不用加载这个模块 

3、手动加载模块 

modprobe overlay
modprobe br_netfilter

# 检查模块情况
lsmod | grep -E 'overlay|br_netfilter'

 

crictl下载的镜像在哪里_crictl下载的镜像在哪里_02

四、部署containerd

mkdir /data/software/containerd
mkdir /etc/containerd
tar zxf containerd-1.6.8-linux-amd64.tar.gz -C /data/software/containerd/
tar zxf crictl-v1.25.0-linux-amd64.tar.gz -C /data/software/containerd/bin/
mv runc.amd64 /data/software/containerd/bin/runc
chmod +x /data/software/containerd/bin/runc

cat > /etc/profile.d/containerd_home.sh <<'EOF'
export CONTAINERD_HOME=/data/software/containerd
export PATH=$PATH:$CONTAINERD_HOME/bin
EOF

source /etc/profile

建立运行时 runc 软链接,不然会报错,说找到这个环境的命令,(个人猜测: 应该是运行时的用户环境不一样,导致在这个用户的环境下找不到该命令: runc) 

ln -s /data/software/containerd/bin/runc /usr/local/bin/

crictl下载的镜像在哪里_redis_03

 

crictl下载的镜像在哪里_容器_04

 五、生成containerd的默认配置文件/etc/containerd/config.toml

containerd config default > /etc/containerd/config.toml

修改数据永久存储位置、修改拉取镜像默认地址(改为国内源)、改为 systemd 作为管理containerd容器服务

mkdir /data/software/containerd/data
 
vim /etc/containerd/config.toml

# 大概在第6行
root = "/data/software/containerd/data"

# 大概在第61行
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.7"

 

crictl下载的镜像在哪里_docker_05

crictl下载的镜像在哪里_kubernetes_06

   

crictl下载的镜像在哪里_redis_07

 六、配置/etc/crictl.yaml

不然会报错

crictl下载的镜像在哪里_容器_08

cat > /etc/crictl.yaml <<'EOF'
runtime-endpoint: "unix:///run/containerd/containerd.sock"
image-endpoint: "unix:///run/containerd/containerd.sock"
timeout: 0
debug: false
pull-image-on-create: false
disable-pull-on-run: false
EOF


# 或者执行下面的两条命令来生成配置文件
crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

七、配置管理 containerd 的 system 配置文件

cat > /usr/lib/systemd/system/containerd.service <<'EOF'
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/data/software/containerd/bin/containerd

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target
EOF

 八、启动 containerd 并设置开机自启

systemctl enable containerd --now

 九、测试

systemctl status containerd.service

crictl images

crictl下载的镜像在哪里_redis_09

 十、命令差别信息

1、crictl缺少对具体镜像的管理能力,crictl是k8s中CRI(容器运行时接口)的客户端,k8s使用该客户端和containerd进行交互,crictl命令运行的默认 命名空间 是在:k8s.io

2、ctr是containerd自带的CLI命令行工具,ctr命令运行的默认 命名空间 是在:default

3、这里我先验证一下

1)ctr查看命名空间

ctr ns ls

crictl下载的镜像在哪里_kubernetes_10

docker.io/library/[镜像名称]:[tag]

ctr image pull docker.io/library/redis:latest

 一、2)命令 crictl 查看镜像情况(查不到上面拉取的镜像)

crictl image ls

crictl下载的镜像在哪里_docker_11

 一、3)命令 ctr 查看镜像情况(可以查到上面拉取的镜像)

ctr image ls

crictl下载的镜像在哪里_docker_12

 二、1)指定 命名空间 拉取镜像

ctr -n k8s.io image pull docker.io/library/redis:latest

二、2)命令 crictl 查看镜像情况(可以查到 ctr 指定 命名空间 下拉取的镜像)

crictl image ls

crictl下载的镜像在哪里_docker_13

 二、3)命令 ctr 查看镜像情况,要指定 命令空间名称 才能查看的到

ctr -n k8s.io image ls

十一、部分命令使用总结

命令

docker

查看命名空间


指定命令运行命令


查看镜像

docker images

拉取镜像

docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5

修改镜像标签

docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5 172.17.0.10:5000/pause:3.5

推送镜像

docker login 172.17.0.42:5000

docker push 172.17.0.10:5000/pause:3.5

导出镜像

docker save 172.17.0.10:5000/pause:3.5 -o pause.tar

删除镜像

docker rmi 172.17.0.10:5000/pause:3.5

导入镜像

docker load -i pause.tar

创建一个新的容器,但不运行

docker create

运行一个新的容器

docker run

查看运行的容器

docker ps

查看容器日志

docker logs

查看容器数据信息

docker inspect

查看容器资源

docker stats

启动/关闭已有的容器

docker start/stop

删除容器

docker rm

在容器内部执行命令

docker exec

命令

ctr(containerd)

查看命名空间

ctr ns ls

指定命令运行命令

ctr -n 命名空间名称(如: k8s.io) 命令(如:image ls)

查看镜像

ctr image ls

拉取镜像

ctr -n k8s.io image pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5

(这里有个问题,如果pull私有仓库,你的私有仓库必须有配置https)

修改镜像标签

ctr -n k8s.io image tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5 172.17.0.10:5000/pause:3.5

推送镜像

ctr -n k8s.io image push 172.17.0.10:5000/pause:3.5 --user admin:Harbor12345

(这里有个问题,你的私有仓库必须有配置https)

导出镜像

ctr -n k8s.io image export pause.tar 172.17.0.10:5000/pause:3.5

删除镜像

ctr -n k8s.io image rm 172.17.0.10:5000/pause:3.5

导入镜像

ctr -n k8s.io image import pause.tar

创建一个新的容器,但不运行

ctr -n k8s.io task/container create docker.io/library/centos:latest centos(运行容器的名称)

运行一个新的容器

ctr -n k8s.io image pull docker.io/library/redis:alpine3.13

ctr -n k8s.io run -d docker.io/library/redis:alpine3.13 redis(运行容器的名称)

查看运行的容器

ctr -n k8s.io task/container ls

查看容器日志


查看容器数据信息

ctr -n k8s.io task/container info redis(运行容器的名称)

查看容器资源


启动/关闭已有的容器

ctr task/container start/kill

删除容器

ctr task/container rm

在容器内部执行命令


命令

crictl(kubernetes)

查看命名空间


指定命令运行命令


查看镜像

crictl images

拉取镜像

crictl pull registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5

修改镜像标签


推送镜像


导出镜像


删除镜像

crictl rmi 172.17.0.10:5000/pause:3.5(它会把源:registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.5一起删了)

导入镜像


创建一个新的容器,但不运行

crictl create

运行一个新的容器

无(最小单元为pod)

查看运行的容器

crictl ps

查看容器日志

crictl logs

查看容器数据信息

crictl inspect

查看容器资源

crictl stats

启动/关闭已有的容器

crictl start/stop

删除容器

crictl rm

在容器内部执行命令

crictl exec

十二、ctr(containerd)命令总结

下载镜像

ctr image pull docker.io/library/redis:alpine3.13

crictl下载的镜像在哪里_容器_14

 查看镜像:ctr images ls 可以简写成: ctr i ls

ctr images ls

crictl下载的镜像在哪里_redis_15

 运行容器

ctr run -d docker.io/library/redis:alpine3.13 redis

查看容器运行信息

ctr container ls

 

crictl下载的镜像在哪里_crictl下载的镜像在哪里_16

 查看容器运行状态(其实是查看任务,这个跟 ctr container ls 是分开的)

ctr task ls

crictl下载的镜像在哪里_kubernetes_17

进入容器(--exec-id redis-sh意思是: 进入容器时的一个名称,是唯一不能重复使用的,如果发送断开再用这个名称就报错了,只能用另外一个名称) 

ctr container exec -t --exec-id redis-sh redis sh

crictl下载的镜像在哪里_docker_18

 暂停容器

ctr task pause redis
ctr task ls

 

crictl下载的镜像在哪里_docker_19

恢复容器为启动状态

ctr tasks resume redis
ctr task ls

crictl下载的镜像在哪里_容器_20

 停止容器

ctr task kill redis
ctr task ls

 

crictl下载的镜像在哪里_docker_21

 停止的容器是不能恢复启动状态的

ctr task resume redis
ctr task ls

crictl下载的镜像在哪里_crictl下载的镜像在哪里_22

删除容器

ctr task delete redis
ctr task ls
ctr container ls
ctr container rm redis
ctr container ls

crictl下载的镜像在哪里_容器_23

 

crictl下载的镜像在哪里_kubernetes_24

只有停止的容器才能删除(所以要先删任务,再来操作删除容器)

crictl下载的镜像在哪里_redis_25

十三、代替docker命令的工具(nerdctl)

nerdctl工具包有精简版和全包版,这里只要精简版就可以了

1、通过代理下载 nerdctl 工具

wget https://ghproxy.com/https://github.com/containerd/nerdctl/releases/download/v0.23.0/nerdctl-0.23.0-linux-amd64.tar.gz

2、安装 nerdctl 工具

tar zxf nerdctl-0.23.0-linux-amd64.tar.gz
mv nerdctl /usr/local/bin/
rm -f containerd-rootless-setuptool.sh containerd-rootless.sh

3、配置docker命令通用

ln -s /usr/local/bin/nerdctl /usr/local/bin/docker

# 配置tab补全,弄了docke的软链接可以用,但不能用tab去补全相关的参数
echo 'source <(nerdctl completion bash)' >> /root/.bashrc

source /root/.bashrc

4、配置默认命名空间

nerdctl ns ls
nerdctl ps
mkdir /etc/nerdctl/

cat >> /etc/nerdctl/nerdctl.toml <<'EOF'
namespace = "k8s.io"
EOF

nerdctl ps

crictl下载的镜像在哪里_crictl下载的镜像在哪里_26

 

十四、配置容器打包工具(buildkit)

1、通过代理下载 buildkit 工具

wget https://ghproxy.com/https://github.com/moby/buildkit/releases/download/v0.10.5/buildkit-v0.10.5.linux-amd64.tar.gz

 2、安装 buildkit 工具

tar -zxvf buildkit-v0.10.5.linux-amd64.tar.gz -C /data/software/containerd/

ll /data/software/containerd/bin/

# 配置 systemd 管理
cat > /etc/systemd/system/buildkit.socket <<'EOF'
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Socket]
ListenStream=%t/buildkit/buildkitd.sock

[Install]
WantedBy=sockets.target
EOF

cat > /etc/systemd/system/buildkit.service <<'EOF'
[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socketDocumentation=https://github.com/moby/buildkit

[Service]
ExecStart=/data/software/containerd/bin/buildkitd --oci-worker=false --containerd-worker=true

[Install]
WantedBy=multi-user.target
EOF

 3、启动 buildkit 工具并设置开机自启

# 重新加载
systemctl daemon-reload

# 启动并设置开启自启
systemctl enable --now buildkit

# 检查
systemctl status buildkit

crictl下载的镜像在哪里_docker_27

4、编写dockerfile

cat > Dockerfile <<'EOF'
FROM alpine:3.13.5

# Here we install GNU libc (aka glibc) and set C.UTF-8 locale as default.
ENV LANG=C.UTF-8
RUN echo "**** install packages ****" && \
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories &&\
    ALPINE_GLIBC_BASE_URL="http://192.168.240.189:88/chfs/shared" && \
    ALPINE_GLIBC_PACKAGE_VERSION="2.33-r0" && \
    ALPINE_GLIBC_BASE_PACKAGE_FILENAME="glibc-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_BIN_PACKAGE_FILENAME="glibc-bin-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    ALPINE_GLIBC_I18N_PACKAGE_FILENAME="glibc-i18n-$ALPINE_GLIBC_PACKAGE_VERSION.apk" && \
    apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
    echo \
        "-----BEGIN PUBLIC KEY-----\
        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZ2u1KJKUu/fW4A25y9m\
        y70AGEa/J3Wi5ibNVGNn1gT1r0VfgeWd0pUybS4UmcHdiNzxJPgoWQhV2SSW1JYu\
        tOqKZF5QSN6X937PTUpNBjUvLtTQ1ve1fp39uf/lEXPpFpOPL88LKnDBgbh7wkCp\
        m2KzLVGChf83MS0ShL6G9EQIAUxLm99VpgRjwqTQ/KfzGtpke1wqws4au0Ab4qPY\
        KXvMLSPLUp7cfulWvhmZSegr5AdhNw5KNizPqCJT8ZrGvgHypXyiFvvAH5YRtSsc\
        Zvo9GI2e2MaZyo9/lvb+LbLEJZKEQckqRj4P26gmASrZEPStwc+yqy1ShHLA0j6m\
        1QIDAQAB\
        -----END PUBLIC KEY-----" | sed 's/   */\n/g' > "/etc/apk/keys/sgerrand.rsa.pub" && \
    wget \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BASE_URL/$ALPINE_GLIBC_PACKAGE_VERSION/$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    apk add --no-cache \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME" && \
    \
    rm "/etc/apk/keys/sgerrand.rsa.pub" && \
    /usr/glibc-compat/bin/localedef --force --inputfile POSIX --charmap UTF-8 "$LANG" || true && \
    echo "export LANG=$LANG" > /etc/profile.d/locale.sh && \
    \
    apk del glibc-i18n && \
    \
    rm -f "/root/.wget-hsts" && \
    apk del .build-dependencies && \
    rm \
        "$ALPINE_GLIBC_BASE_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_BIN_PACKAGE_FILENAME" \
        "$ALPINE_GLIBC_I18N_PACKAGE_FILENAME"


RUN apk update --no-cache && apk add ca-certificates --no-cache && \
    apk add tzdata --no-cache && \
    ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone
EOF

5、测试打包镜像

docker build -t base-alpine .
nerdctl image ls

crictl下载的镜像在哪里_redis_28