Containerd 介绍、安装和使用

Containerd介绍、安装和使用

文章目录

  • Containerd介绍、安装和使用
  • 1.containerd是什么?
  • 2.Containerd安装
    • 2.1 主机初始化
      • 2.1.1 设置ip地址
      • 2.1.2 配置镜像源
      • 2.1.3 关闭防火墙
      • 2.1.4 禁用SELinux
      • 2.1.5 禁用swap
      • 2.1.6 设置时区
    • 2.2 安装 containerd
      • 2.2.1 内核参数调整
      • 2.2.2 包安装 Containerd
        • 2.2.2.1 Rocky或CentOS安装containerd
        • 2.2.2.2 Ubuntu安装containerd
        • 2.2.2.3 配置 Containerd
        • 2.2.2.4 安装crictl工具
        • 2.2.2.5 安装CNI插件
      • 2.2.3 二进制安装 Containerd
        • 2.2.3.1 安装 containerd
        • 2.2.3.2 配置Containerd
      • 2.2.4 containerd 客户端工具 nerdctl
      • 2.2.5 一键安装containerd脚本
        • 2.2.5.1 基于镜像仓库一键安装containerd脚本
        • 2.2.5.2 基于二进制包一键安装containerd脚本
      • 2.2.6 Containerd 常见命令操作
        • 2.2.6.1 ctr命令使用
      • 2.2.7 nerdctl命令实战操作

1.containerd是什么?

在这里插入图片描述

containerd 是一种行业标准的容器运行时,强调简单、健壮和可移植性。它是 Linux 和 Windows 下的守护进程,可以管理其主机系统的整个容器生命周期:镜像传输和存储、容器执行和监管、底层存储和网络附加等。

containerd 是 CNCF 的成员,具有 "毕业 "资格。

containerd 的设计目的是嵌入到更大的系统中,而不是由开发人员或最终用户直接使用。

t1-2

2.Containerd安装

2.1 主机初始化

2.1.1 设置ip地址

Rocky 9和CentOS Stream 9:

# Rocky 9和CentOS Stream 9默认支持修改网卡名。
[root@rocky9 ~]# grep 'plugins' /etc/NetworkManager/NetworkManager.conf 
#plugins=keyfile,ifcfg-rh
# 因为网卡命名方式默认是keyfile,默认不支持修改网卡名,既然官方已经默认是keyfile那这里就不去更改网卡名了。

[root@rocky9 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`

[root@rocky9 ~]# nmcli con delete ${ETHNAME} && nmcli connection add type ethernet con-name ${ETHNAME} ifname ${ETHNAME} ipv4.method manual ipv4.address "172.31.0.9/21" ipv4.gateway "172.31.0.2" ipv4.dns "223.5.5.5,180.76.76.76" autoconnect yes && nmcli con reload && nmcli con up ${ETHNAME}
# 172.31.0.9/21中172.31.0.9是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。

[root@rocky9 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:37:62:95 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 172.31.0.9/21 brd 172.31.7.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::51ca:fd5d:3552:677d/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
# 可以看到ip地址已修改。

Rocky 8、CentOS Stream 8和CentOS 7:

# Rocky 8、CentOS Stream 8和CentOS 7支持修改网卡名。
[root@rocky8 ~]# grep 'plugins' /etc/NetworkManager/NetworkManager.conf 
#plugins=ifcfg-rh
# 因为网卡命名方式默认是ifcfg-rh,支持修改网卡名。

# 修改网卡名称配置文件
[root@rocky8 ~]# sed -ri.bak '/^GRUB_CMDLINE_LINUX=/s@"$@ net.ifnames=0 biosdevname=0"@' /etc/default/grub
[root@rocky8 ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
done

# 修改网卡文件名
[root@rocky8 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`
[root@rocky8 ~]# mv /etc/sysconfig/network-scripts/ifcfg-${ETHNAME} /etc/sysconfig/network-scripts/ifcfg-eth0

[root@rocky8 ~]# shutdown -r now


[root@rocky8 ~]# nmcli dev
DEVICE  TYPE      STATE      CONNECTION         
eth0    ethernet  connected  Wired connection 1 
lo      loopback  unmanaged  --
# 可以看到CONNECTION的名字是Wired connection 1,要改名才可以下面设置。

[root@rocky8 ~]# ETHNAME=`ip addr | awk -F"[ :]" '/^2/{print $3}'`

[root@rocky8 ~]# nmcli connection modify "Wired connection 1" con-name ${ETHNAME}
[root@rocky8 ~]# nmcli dev
DEVICE  TYPE      STATE      CONNECTION 
eth0    ethernet  connected  eth0       
lo      loopback  unmanaged  --  

# 修改ip地址
[root@rocky8 ~]# nmcli con delete ${ETHNAME} && nmcli connection add type ethernet con-name ${ETHNAME} ifname ${ETHNAME} ipv4.method manual ipv4.address "172.31.0.8/21" ipv4.gateway "172.31.0.2" ipv4.dns "223.5.5.5,180.76.76.76" autoconnect yes && nmcli con reload && nmcli dev up eth0
# 172.31.0.8/21中172.31.0.8是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。

[root@rocky8 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:6f:65:d3 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 172.31.0.8/21 brd 172.31.7.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e9c9:aa93:4a58:2cc2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。

Ubuntu:

# Ubuntu先启用root用户,并设置密码
raymond@ubuntu2204:~$ cat set_root_login.sh 
#!/bin/bash

read -p "请输入密码: " PASSWORD
echo ${PASSWORD} |sudo -S sed -ri 's@#(PermitRootLogin )prohibit-password@\1yes@' /etc/ssh/sshd_config
sudo systemctl restart sshd
sudo -S passwd root <<-EOF
${PASSWORD}
${PASSWORD}
EOF

raymond@ubuntu2204:~$ bash set_root_login.sh 
请输入密码: 123456
[sudo] password for raymond: New password: Retype new password: passwd: password updated successfully

raymond@ubuntu2204:~$ rm -rf set_root_login.sh

# 使用root登陆,修改网卡名
root@ubuntu2204:~# sed -ri.bak '/^GRUB_CMDLINE_LINUX=/s@"$@net.ifnames=0 biosdevname=0"@' /etc/default/grub
root@ubuntu2204:~# grub-mkconfig -o /boot/grub/grub.cfg
Sourcing file `/etc/default/grub'
Sourcing file `/etc/default/grub.d/init-select.cfg'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.15.0-88-generic
Found initrd image: /boot/initrd.img-5.15.0-88-generic
Warning: os-prober will not be executed to detect other bootable partitions.
Systems on them will not be added to the GRUB boot configuration.
Check GRUB_DISABLE_OS_PROBER documentation entry.
done

# Ubuntu 20.04设置ip地址
root@ubuntu2004:~# cat > /etc/netplan/00-installer-config.yaml <<-EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      dhcp6: no
      addresses: [172.31.0.20/21] 
      gateway4: 172.31.0.2
      nameservers:
        addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu20.04网卡配置文件是00-installer-config.yaml;172.31.0.20/21中172.31.0.20是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。

# Ubuntu 18.04设置ip地址
root@ubuntu1804:~# cat > /etc/netplan/01-netcfg.yaml <<-EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      dhcp6: no
      addresses: [172.31.0.18/21] 
      gateway4: 172.31.0.2
      nameservers:
        addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu18.04网卡配置文件是01-netcfg.yaml;172.31.0.18/21中172.31.0.18是ip地址,21是子网位数;172.31.0.2是网关地址;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。

root@ubuntu2004:~# shutdown -r now

root@ubuntu2004:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:e5:98:6f brd ff:ff:ff:ff:ff:ff
    inet 172.31.0.20/21 brd 172.31.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fee5:986f/64 scope link 
       valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。

# Ubuntu 22.04设置ip地址
root@ubuntu2204:~# cat > /etc/netplan/00-installer-config.yaml <<-EOF
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: no
      dhcp6: no
      addresses: [172.31.0.22/21]
      routes:
        - to: default
          via: 172.31.0.2
      nameservers:
        addresses: [223.5.5.5, 180.76.76.76]
EOF
# 说明:Ubuntu22.04网卡配置文件是00-installer-config.yaml;172.31.0.22/21中172.31.0.22是ip地址,21是子网位数;172.31.0.2是网关地址,Ubuntu 22.04设置网关地址的方法发生了改变,参考上面的方法;223.5.5.5, 180.76.76.76都是DNS,根据自己的需求修改。

root@ubuntu2204:~# shutdown -r now

# 重启后使用新设置的ip登陆
root@ubuntu2204:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:a7:be:f2 brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    altname ens33
    inet 172.31.0.22/21 brd 172.31.7.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fea7:bef2/64 scope link 
       valid_lft forever preferred_lft forever
# 重启系统后可以看到网卡名已经修改成eth0,ip地址也已修改。

2.1.2 配置镜像源

Rocky 8和9:

MIRROR=mirrors.sjtug.sjtu.edu.cn
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://dl.rockylinux.org/$contentdir|baseurl=https://'${MIRROR}'/rocky|g' /etc/yum.repos.d/[Rr]ocky*.repo

dnf clean all && dnf makecache

CentOS Stream 9:

cat update_mirror.pl
#!/usr/bin/perl

use strict;
use warnings;
use autodie;

# 要修改镜像源,请去修改url变量!
my $url = 'mirrors.aliyun.com';
my $mirrors = "https://$url/centos-stream";

if (@ARGV < 1) {
    die "Usage: $0 <filename1> <filename2> ...\n";
}

while (my $filename = shift @ARGV) {
    my $backup_filename = $filename . '.bak';
    rename $filename, $backup_filename;

    open my $input, "<", $backup_filename;
    open my $output, ">", $filename;

    while (<$input>) {
        s/^metalink/# metalink/;

        if (m/^name/) {
            my (undef, $repo, $arch) = split /-/;
            $repo =~ s/^\s+|\s+$//g;
            ($arch = defined $arch ? lc($arch) : '') =~ s/^\s+|\s+$//g;

            if ($repo =~ /^Extras/) {
                $_ .= "baseurl=${mirrors}/SIGs/\$releasever-stream/extras" . ($arch eq 'source' ? "/${arch}/" : "/\$basearch/") . "extras-common\n";
            } else {
                $_ .= "baseurl=${mirrors}/\$releasever-stream/$repo" . ($arch eq 'source' ? "/" : "/\$basearch/") . ($arch ne '' ? "${arch}/tree/" : "os") . "\n";
            }
        }

        print $output $_;
    }
}

rpm -q perl &> /dev/null || { echo -e "\\033[01;31m "安装perl工具,请稍等..."\033[0m";yum -y install perl ; }

perl ./update_mirror.pl /etc/yum.repos.d/centos*.repo

dnf clean all && dnf makecache

CentOS Stream 8:

MIRROR=mirrors.aliyun.com
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org/$contentdir|baseurl=https://'${MIRROR}'/centos|g' /etc/yum.repos.d/CentOS-*.repo

dnf clean all && dnf makecache

CentOS 7:

MIRROR=mirrors.aliyun.com
sed -i.bak -e 's|^mirrorlist=|#mirrorlist=|g' -e 's|^#baseurl=http://mirror.centos.org|baseurl=https://'${MIRROR}'|g' /etc/yum.repos.d/CentOS-*.repo

yum clean all && yum makecache

Ubuntu 22.04和20.04:

MIRROR=mirrors.aliyun.com
OLD_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu/? $(lsb_release -cs) main.*@\2@p" /etc/apt/sources.list`

sed -i.bak 's/'${OLD_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.list

apt update

Ubuntu 18.04:

MIRROR=mirrors.aliyun.com
OLD_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu/? $(lsb_release -cs) main.*@\2@p" /etc/apt/sources.list`

sed -i.bak 's/'${OLD_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.list

SECURITY_MIRROR=`sed -rn "s@^deb http(.*)://(.*)/ubuntu $(lsb_release -cs)-security main.*@\2@p" /etc/apt/sources.list`

sed -i.bak 's/'${SECURITY_MIRROR}'/'${MIRROR}'/g' /etc/apt/sources.list

apt update

2.1.3 关闭防火墙

# Rocky和CentOS
systemctl disable --now firewalld

# CentOS 7
systemctl disable --now NetworkManager

# Ubuntu
systemctl disable --now ufw

2.1.4 禁用SELinux

#CentOS
setenforce 0
sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config

#Ubuntu
Ubuntu没有安装SELinux,不用设置

2.1.5 禁用swap

sed -ri 's/.*swap.*/#&/' /etc/fstab
swapoff -a

# Ubuntu 20.04和22.04,执行下面命令
sed -ri 's/.*swap.*/#&/' /etc/fstab
SD_NAME=`lsblk|awk -F"[ └─]" '/SWAP/{printf $3}'`
systemctl mask dev-${SD_NAME}.swap
swapoff -a

2.1.6 设置时区

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo 'Asia/Shanghai' >/etc/timezone

#Ubuntu还要设置下面内容
cat >> /etc/default/locale <<-EOF
LC_TIME=en_DK.UTF-8
EOF

2.2 安装 containerd

2.2.1 内核参数调整

如果是安装 Docker 会自动配置以下的内核参数,而无需手动实现

但是如果安装Contanerd,还需手动配置

允许 iptables 检查桥接流量,若要显式加载此模块,需运行 modprobe br_netfilter

为了让 Linux 节点的 iptables 能够正确查看桥接流量,还需要确认net.bridge.bridge-nf-call-iptables 设置为 1。

配置Containerd所需的模块:

[root@rocky9 ~]# cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

加载模块:

[root@rocky9 ~]# modprobe -- overlay
[root@rocky9 ~]# modprobe -- br_netfilter

配置Containerd所需的内核:

[root@rocky9 ~]# cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

加载内核:

[root@rocky9 ~]# sysctl --system

2.2.2 包安装 Containerd

2.2.2.1 Rocky或CentOS安装containerd
# step 1: 安装必要的一些系统工具
[root@rocky9 ~]# yum -y install yum-utils

# Step 2: 添加软件源信息
[root@rocky9 ~]# yum-config-manager --add-repo https://mirrors.tencent.com/docker-ce/linux/centos/docker-ce.repo

# Step 3: 更新Docker-CE镜像源
[root@rocky9 ~]# yum clean all
[root@rocky9 ~]# yum makecache

# 安装指定版本的containerd:
# Step 4: 查找containerd.的版本:
[root@rocky9 ~]# yum list containerd.io --showduplicates
Last metadata expiration check: 0:00:15 ago on Thu 15 Feb 2024 01:39:55 PM CST.
Available Packages
containerd.io.x86_64                                   1.6.4-3.1.el9                                    docker-ce-stable
containerd.io.x86_64                                   1.6.6-3.1.el9                                    docker-ce-stable
containerd.io.x86_64                                   1.6.7-3.1.el9                                    docker-ce-stable
containerd.io.x86_64                                   1.6.8-3.1.el9                                    docker-ce-stable
containerd.io.x86_64                                   1.6.9-3.1.el9                                    docker-ce-stable
containerd.io.x86_64                                   1.6.10-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.11-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.12-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.13-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.14-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.15-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.16-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.18-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.19-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.20-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.21-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.22-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.24-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.25-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.26-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.27-3.1.el9                                   docker-ce-stable
containerd.io.x86_64                                   1.6.28-3.1.el9                                   docker-ce-stabl

# Step5: 安装指定版本的containerd: (VERSION例如上面的1.6.28)
[root@rocky9 ~]# yum -y install containerd.io-1.6.28
2.2.2.2 Ubuntu安装containerd
# step 1: 安装必要的一些系统工具
root@ubuntu2204:~# apt update
root@ubuntu2204:~# apt -y install apt-transport-https ca-certificates curl software-properties-common

# step 2: 安装GPG证书
root@ubuntu2204:~# curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

# Step 3: 写入软件源信息
root@ubuntu2204:~# add-apt-repository -y "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu/  $(lsb_release -cs) stable"

# Step 4: 更新Containerd镜像源
root@ubuntu2204:~# apt update

# 安装指定版本的Containerd:
# Step 5: 查找Containerd的版本:
root@ubuntu2204:~# apt-cache madison containerd.io
containerd.io |   1.6.28-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.27-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.26-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.25-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.24-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.22-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.21-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.20-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.19-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.18-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.16-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.15-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.14-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.13-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.12-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.11-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.6.10-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |    1.6.9-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |    1.6.8-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |    1.6.7-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |    1.6.6-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |    1.6.4-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.5.11-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages
containerd.io |   1.5.10-1 | https://mirrors.aliyun.com/docker-ce/linux/ubuntu jammy/stable amd64 Packages

# Step 6: 安装指定版本的containerd: (VERSION例如上面的1.6.12-0ubuntu1~22.04.3)
root@ubuntu2204:~# apt -y install containerd.io=1.6.28-1
2.2.2.3 配置 Containerd

配置Containerd的配置文件:

[root@rocky9 ~]# containerd config default | tee /etc/containerd/config.toml

将Containerd的Cgroup改为Systemd和修改containerd配置sandbox_image 镜像源设置为阿里google_containers镜像源:

[root@rocky9 ~]# vim /etc/containerd/config.toml
...
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] # 在这行下面找到SystemdCgroup。
...
# 把下面内容
            SystemdCgroup = false
# 改成下面内容
            SystemdCgroup = true # 把SystemdCgroup里的false改成true。
...
# 把下面内容
    sandbox_image = "registry.k8s.io/pause:3.6"
# 改成下面内容
    sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6" # 把sandbox_image的镜像改为阿里镜像源。

# 使用下面命令修改
[root@rocky9 ~]# sed -ri -e 's/(.*SystemdCgroup = ).*/\1true/' -e "s#registry.k8s.io#registry.aliyuncs.com/google_containers#g" /etc/containerd/config.toml

配置镜像加速:

[root@rocky9 ~]# vim /etc/containerd/config.toml
...
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors] # 在这行下面配置镜像加速,注意每行前面都有2个缩进。
#下面两行是配置镜像加速
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]

# 使用下面命令修改
[root@rocky9 ~]# sed -i '/.*registry.mirrors.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]' /etc/containerd/config.toml

启动Containerd,并配置开机自启动:

[root@rocky9 ~]# systemctl daemon-reload && systemctl enable --now containerd

# Ubuntu默认安装完Containerd已经启动了服务,需要重启一下服务才能配置生效。
root@ubuntu2204:~# systemctl restart containerd

[root@rocky9 ~]# systemctl is-active containerd
active
2.2.2.4 安装crictl工具
# Rocky和CentOS
[root@rocky9 ~]# rpm -ql containerd.io
/etc/containerd
/etc/containerd/config.toml
/usr/bin/containerd
/usr/bin/containerd-shim
/usr/bin/containerd-shim-runc-v1
/usr/bin/containerd-shim-runc-v2
/usr/bin/ctr
/usr/bin/runc
/usr/lib/.build-id
/usr/lib/.build-id/50
/usr/lib/.build-id/50/6dc3841de9b492f9ccb6f0ea69ef642d755c1b
/usr/lib/.build-id/d6
/usr/lib/.build-id/d6/0988ba571e825119ce555ccc01a588bc8a23bf
/usr/lib/.build-id/f4
/usr/lib/.build-id/f4/20449290a3275cc0ac97f228938e87a88d299c
/usr/lib/systemd/system/containerd.service
/usr/share/doc/containerd.io
/usr/share/doc/containerd.io/README.md
/usr/share/licenses/containerd.io
/usr/share/licenses/containerd.io/LICENSE
/usr/share/man/man5/containerd-config.toml.5
/usr/share/man/man8/containerd-config.8
/usr/share/man/man8/containerd.8
/usr/share/man/man8/ctr.8
# 可以看到containerd已经装了ctr工具和runc,但是没有装crictl工具

# Ubuntu
root@ubuntu2204:~# dpkg -L containerd.io
/.
/etc
/etc/containerd
/etc/containerd/config.toml
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/containerd.service
/usr
/usr/bin
/usr/bin/containerd
/usr/bin/containerd-shim
/usr/bin/containerd-shim-runc-v1
/usr/bin/containerd-shim-runc-v2
/usr/bin/ctr
/usr/bin/runc
/usr/share
/usr/share/doc
/usr/share/doc/containerd.io
/usr/share/doc/containerd.io/changelog.Debian.gz
/usr/share/doc/containerd.io/copyright
/usr/share/man
/usr/share/man/man5
/usr/share/man/man5/containerd-config.toml.5.gz
/usr/share/man/man8
/usr/share/man/man8/containerd-config.8.gz
/usr/share/man/man8/containerd.8.gz
/usr/share/man/man8/ctr.8.gz
# 可以看到containerd已经装了ctr工具和runc,但是没有装crictl工具

[root@rocky9 ~]# wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz

[root@rocky9 ~]# tar zxvf crictl-v1.29.0-linux-amd64.tar.gz -C /usr/local/bin

配置crictl客户端连接的运行时位置:

[root@rocky9 ~]# cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

[root@rocky9 ~]# systemctl restart containerd

查看信息:

[root@rocky9 ~]# ctr version
Client:
  Version:  1.6.28
  Revision: ae07eda36dd25f8a1b98dfbf587313b99c0190bb
  Go version: go1.20.13

Server:
  Version:  1.6.28
  Revision: ae07eda36dd25f8a1b98dfbf587313b99c0190bb
  UUID: cc7c669c-368d-4d06-ac44-761b10a28f5d

[root@rocky9 ~]# crictl version
Version:  0.1.0
RuntimeName:  containerd
RuntimeVersion:  1.6.28
RuntimeApiVersion:  v1

[root@rocky9 ~]# crictl info
{
...
  "lastCNILoadStatus": "cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config",
  "lastCNILoadStatus.default": "cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config"
}
# 这里提示cni插件报错,因为没有装containerd的CNI插件.
2.2.2.5 安装CNI插件
[root@rocky9 ~]# wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz

[root@rocky9 ~]# mkdir -p /opt/cni/bin/
[root@rocky9 ~]# tar xzvf cni-plugins-linux-amd64-v1.4.0.tgz -C /opt/cni/bin/

# cni配置文件
[root@rocky9 ~]# mkdir -p /etc/cni/net.d/
[root@rocky9 ~]# cat > /etc/cni/net.d/10-containerd-net.conflist <<EOF
{
  "cniVersion": "1.0.0",
  "name": "containerd-net",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "cni0",
      "isGateway": true,
      "ipMasq": true,
      "promiscMode": true,
      "ipam": {
        "type": "host-local",
        "ranges": [
          [{
            "subnet": "10.88.0.0/16"
          }],
          [{
            "subnet": "2001:4860:4860::/64"
          }]
        ],
        "routes": [
          { "dst": "0.0.0.0/0" },
          { "dst": "::/0" }
        ]
      }
    },
    {
      "type": "portmap",
      "capabilities": {"portMappings": true}
    }
  ]
}
EOF

[root@rocky9 ~]# systemctl restart containerd
[root@rocky9 ~]# crictl info
{
  "status": {
    "conditions": [
      {
        "type": "RuntimeReady",
        "status": true,
        "reason": "",
        "message": ""
      },
      {
        "type": "NetworkReady",
        "status": true,
        "reason": "",
        "message": ""
      }
    ]
  },
  "cniconfig": {
    "PluginDirs": [
      "/opt/cni/bin"
    ],
    "PluginConfDir": "/etc/cni/net.d",
    "PluginMaxConfNum": 1,
    "Prefix": "eth",
    "Networks": [
      {
        "Config": {
          "Name": "cni-loopback",
          "CNIVersion": "0.3.1",
          "Plugins": [
            {
              "Network": {
                "type": "loopback",
                "ipam": {},
                "dns": {}
              },
              "Source": "{\"type\":\"loopback\"}"
            }
          ],
          "Source": "{\n\"cniVersion\": \"0.3.1\",\n\"name\": \"cni-loopback\",\n\"plugins\": [{\n  \"type\": \"loopback\"\n}]\n}"
        },
        "IFName": "lo"
      },
      {
        "Config": {
          "Name": "containerd-net",
          "CNIVersion": "1.0.0",
          "Plugins": [
            {
              "Network": {
                "type": "bridge",
                "ipam": {
                  "type": "host-local"
                },
                "dns": {}
              },
              "Source": "{\"bridge\":\"cni0\",\"ipMasq\":true,\"ipam\":{\"ranges\":[[{\"subnet\":\"10.88.0.0/16\"}],[{\"subnet\":\"2001:4860:4860::/64\"}]],\"routes\":[{\"dst\":\"0.0.0.0/0\"},{\"dst\":\"::/0\"}],\"type\":\"host-local\"},\"isGateway\":true,\"promiscMode\":true,\"type\":\"bridge\"}"
            },
            {
              "Network": {
                "type": "portmap",
                "capabilities": {
                  "portMappings": true
                },
                "ipam": {},
                "dns": {}
              },
              "Source": "{\"capabilities\":{\"portMappings\":true},\"type\":\"portmap\"}"
            }
          ],
          "Source": "{\n  \"cniVersion\": \"1.0.0\",\n  \"name\": \"containerd-net\",\n  \"plugins\": [\n    {\n      \"type\": \"bridge\",\n      \"bridge\": \"cni0\",\n      \"isGateway\": true,\n      \"ipMasq\": true,\n      \"promiscMode\": true,\n      \"ipam\": {\n        \"type\": \"host-local\",\n        \"ranges\": [\n          [{\n            \"subnet\": \"10.88.0.0/16\"\n          }],\n          [{\n            \"subnet\": \"2001:4860:4860::/64\"\n          }]\n        ],\n        \"routes\": [\n          { \"dst\": \"0.0.0.0/0\" },\n          { \"dst\": \"::/0\" }\n        ]\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\"portMappings\": true}\n    }\n  ]\n}\n"
        },
        "IFName": "eth0"
      }
    ]
  },
  "config": {
    "containerd": {
      "snapshotter": "overlayfs",
      "defaultRuntimeName": "runc",
      "defaultRuntime": {
        "runtimeType": "",
        "runtimePath": "",
        "runtimeEngine": "",
        "PodAnnotations": [],
        "ContainerAnnotations": [],
        "runtimeRoot": "",
        "options": {},
        "privileged_without_host_devices": false,
        "baseRuntimeSpec": "",
        "cniConfDir": "",
        "cniMaxConfNum": 0
      },
      "untrustedWorkloadRuntime": {
        "runtimeType": "",
        "runtimePath": "",
        "runtimeEngine": "",
        "PodAnnotations": [],
        "ContainerAnnotations": [],
        "runtimeRoot": "",
        "options": {},
        "privileged_without_host_devices": false,
        "baseRuntimeSpec": "",
        "cniConfDir": "",
        "cniMaxConfNum": 0
      },
      "runtimes": {
        "runc": {
          "runtimeType": "io.containerd.runc.v2",
          "runtimePath": "",
          "runtimeEngine": "",
          "PodAnnotations": [],
          "ContainerAnnotations": [],
          "runtimeRoot": "",
          "options": {
            "BinaryName": "",
            "CriuImagePath": "",
            "CriuPath": "",
            "CriuWorkPath": "",
            "IoGid": 0,
            "IoUid": 0,
            "NoNewKeyring": false,
            "NoPivotRoot": false,
            "Root": "",
            "ShimCgroup": "",
            "SystemdCgroup": true
          },
          "privileged_without_host_devices": false,
          "baseRuntimeSpec": "",
          "cniConfDir": "",
          "cniMaxConfNum": 0
        }
      },
      "noPivot": false,
      "disableSnapshotAnnotations": true,
      "discardUnpackedLayers": false,
      "ignoreRdtNotEnabledErrors": false
    },
    "cni": {
      "binDir": "/opt/cni/bin",
      "confDir": "/etc/cni/net.d",
      "maxConfNum": 1,
      "confTemplate": "",
      "ipPref": ""
    },
    "registry": {
      "configPath": "",
      "mirrors": {
        "docker.io": {
          "endpoint": [
            "https://registry.docker-cn.com",
            "http://hub-mirror.c.163.com",
            "https://docker.mirrors.ustc.edu.cn"
          ]
        }
      },
      "configs": {},
      "auths": {},
      "headers": {}
    },
    "imageDecryption": {
      "keyModel": "node"
    },
    "disableTCPService": true,
    "streamServerAddress": "127.0.0.1",
    "streamServerPort": "0",
    "streamIdleTimeout": "4h0m0s",
    "enableSelinux": false,
    "selinuxCategoryRange": 1024,
    "sandboxImage": "registry.aliyuncs.com/google_containers/pause:3.6",
    "statsCollectPeriod": 10,
    "systemdCgroup": false,
    "enableTLSStreaming": false,
    "x509KeyPairStreaming": {
      "tlsCertFile": "",
      "tlsKeyFile": ""
    },
    "maxContainerLogSize": 16384,
    "disableCgroup": false,
    "disableApparmor": false,
    "restrictOOMScoreAdj": false,
    "maxConcurrentDownloads": 3,
    "disableProcMount": false,
    "unsetSeccompProfile": "",
    "tolerateMissingHugetlbController": true,
    "disableHugetlbController": true,
    "device_ownership_from_security_context": false,
    "ignoreImageDefinedVolumes": false,
    "netnsMountsUnderStateDir": false,
    "enableUnprivilegedPorts": false,
    "enableUnprivilegedICMP": false,
    "containerdRootDir": "/var/lib/containerd",
    "containerdEndpoint": "/run/containerd/containerd.sock",
    "rootDir": "/var/lib/containerd/io.containerd.grpc.v1.cri",
    "stateDir": "/run/containerd/io.containerd.grpc.v1.cri"
  },
  "golang": "go1.20.13",
  "lastCNILoadStatus": "OK",
  "lastCNILoadStatus.default": "OK"
}
# 现在就没有cni插件报错了,到此containerd就安装完成了。

2.2.3 二进制安装 Containerd

官方下载链接:

https://github.com/containerd/containerd

Containerd有三种二进制安装包:

  • containerd-xxx :包含containerd和ctr,不包含runC、crictl、systemd 配置文件等相关文件,需要单独安装runC

    [root@rocky9-2 ~]# wget https://github.com/containerd/containerd/releases/download/v1.7.12/containerd-1.7.12-linux-amd64.tar.gz
    
    [root@rocky9-2 ~]# tar tf containerd-1.7.12-linux-amd64.tar.gz
    bin/
    bin/containerd-shim
    bin/containerd-stress
    bin/containerd-shim-runc-v1
    bin/ctr
    bin/containerd
    bin/containerd-shim-runc-v2
    
  • cri-containerd-xxx:包含containerd、runC,ctr、crictl、systemd 配置文件等相关文件,不包含cni插件,k8s不需要containerd的cni插件,所以选择这个二进制包安装

    [root@rocky9-2 ~]# wget https://github.com/containerd/containerd/releases/download/v1.7.12/cri-containerd-1.7.12-linux-amd64.tar.gz
    
    [root@rocky9-2 ~]# tar tf cri-containerd-1.7.12-linux-amd64.tar.gz
    cri-containerd.DEPRECATED.txt
    etc/crictl.yaml
    etc/systemd/
    etc/systemd/system/
    etc/systemd/system/containerd.service
    usr/
    usr/local/
    usr/local/bin/
    usr/local/bin/containerd-shim
    usr/local/bin/containerd-stress
    usr/local/bin/containerd-shim-runc-v1
    usr/local/bin/ctr
    usr/local/bin/crictl
    usr/local/bin/ctd-decoder
    usr/local/bin/critest
    usr/local/bin/containerd
    usr/local/bin/containerd-shim-runc-v2
    usr/local/sbin/
    usr/local/sbin/runc
    opt/containerd/
    opt/containerd/cluster/
    opt/containerd/cluster/version
    opt/containerd/cluster/gce/
    opt/containerd/cluster/gce/cloud-init/
    opt/containerd/cluster/gce/cloud-init/node.yaml
    opt/containerd/cluster/gce/cloud-init/master.yaml
    opt/containerd/cluster/gce/env
    opt/containerd/cluster/gce/cni.template
    opt/containerd/cluster/gce/configure.sh
    
  • cri-containerd-cni-xxx:包含containerd、runc、ctr、crictl、cni插件、systemd 配置文件等相关文件

    [root@rocky9-2 ~]# wget https://github.com/containerd/containerd/releases/download/v1.7.12/cri-containerd-cni-1.7.12-linux-amd64.tar.gz
    
    [root@rocky9-2 ~]# tar tf cri-containerd-cni-1.7.12-linux-amd64.tar.gz 
    cri-containerd.DEPRECATED.txt
    etc/
    etc/systemd/
    etc/systemd/system/
    etc/systemd/system/containerd.service
    etc/cni/
    etc/cni/net.d/
    etc/cni/net.d/10-containerd-net.conflist
    etc/crictl.yaml
    usr/
    usr/local/
    usr/local/bin/
    usr/local/bin/containerd-shim
    usr/local/bin/containerd-stress
    usr/local/bin/containerd-shim-runc-v1
    usr/local/bin/ctr
    usr/local/bin/crictl
    usr/local/bin/ctd-decoder
    usr/local/bin/critest
    usr/local/bin/containerd
    usr/local/bin/containerd-shim-runc-v2
    usr/local/sbin/
    usr/local/sbin/runc
    opt/
    opt/cni/
    opt/cni/bin/
    opt/cni/bin/bandwidth
    opt/cni/bin/firewall
    opt/cni/bin/host-local
    opt/cni/bin/static
    opt/cni/bin/vrf
    opt/cni/bin/dhcp
    opt/cni/bin/vlan
    opt/cni/bin/loopback
    opt/cni/bin/sbr
    opt/cni/bin/tuning
    opt/cni/bin/macvlan
    opt/cni/bin/portmap
    opt/cni/bin/dummy
    opt/cni/bin/bridge
    opt/cni/bin/host-device
    opt/cni/bin/ptp
    opt/cni/bin/ipvlan
    opt/containerd/
    opt/containerd/cluster/
    opt/containerd/cluster/version
    opt/containerd/cluster/gce/
    opt/containerd/cluster/gce/cloud-init/
    opt/containerd/cluster/gce/cloud-init/node.yaml
    opt/containerd/cluster/gce/cloud-init/master.yaml
    opt/containerd/cluster/gce/env
    opt/containerd/cluster/gce/cni.template
    opt/containerd/cluster/gce/configure.sh
    
2.2.3.1 安装 containerd
[root@rocky9-2 ~]# wget https://github.com/containerd/containerd/releases/download/v1.7.12/cri-containerd-cni-1.7.12-linux-amd64.tar.gz

# cri-containerd-cni-1.7.12-linux-amd64.tar.gz 压缩包中已经按照官方二进制部署推荐的目录结构布局好。 里面包含了 systemd 配置文件,containerd 和ctr、crictl、cni插件等部署文件。 将解压缩到系统的根目录 / 中:

[root@rocky9-2 ~]# tar xf cri-containerd-cni-1.7.12-linux-amd64.tar.gz -C /
2.2.3.2 配置Containerd

配置Containerd的配置文件:

[root@rocky9-2 ~]# mkdir -p /etc/containerd
[root@rocky9-2 ~]# containerd config default | tee /etc/containerd/config.toml

将Containerd的Cgroup改为Systemd和修改containerd配置sandbox_image 镜像源设置为阿里google_containers镜像源:

[root@rocky9 ~]# vim /etc/containerd/config.toml
...
          [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] # 在这行下面找到SystemdCgroup。
...
# 把下面内容
            SystemdCgroup = false
# 改成下面内容
            SystemdCgroup = true # 把SystemdCgroup里的false改成true。
...
# 把下面内容
    sandbox_image = "registry.k8s.io/pause:3.8"
# 改成下面内容
    sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.8" # 把sandbox_image的镜像改为阿里镜像源。

#使用下面命令修改
[root@rocky9 ~]# sed -ri -e 's/(.*SystemdCgroup = ).*/\1true/' -e "s#registry.k8s.io#registry.aliyuncs.com/google_containers#g" /etc/containerd/config.toml

配置镜像加速:

[root@rocky9 ~]# vim /etc/containerd/config.toml
...
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors] # 在这行下面配置镜像加速,注意每行前面都有2个缩进。
#下面两行是配置镜像加速
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]

#使用下面命令修改
[root@rocky9 ~]# sed -i '/.*registry.mirrors.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]' /etc/containerd/config.toml

使用crictl命令之前,需要先配置/etc/crictl.yaml如下:

[root@rocky9 ~]# cat > /etc/crictl.yaml <<EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

也可以通过命令进行设置:

crictl config runtime-endpoint unix:///run/containerd/containerd.sock
crictl config image-endpoint unix:///run/containerd/containerd.sock

启动Containerd,并配置开机自启动:

[root@rocky9 ~]# systemctl daemon-reload && systemctl enable --now containerd

[root@rocky9 ~]# systemctl is-active containerd
active

查看信息:

[root@rocky9-2 ~]# ctr version
Client:
  Version:  v1.7.12
  Revision: 71909c1814c544ac47ab91d2e8b84718e517bb99
  Go version: go1.20.13

Server:
  Version:  v1.7.12
  Revision: 71909c1814c544ac47ab91d2e8b84718e517bb99
  UUID: 46be7315-15ce-4a1f-922a-4902732c64a6

[root@rocky9-2 ~]# crictl version
Version:  0.1.0
RuntimeName:  containerd
RuntimeVersion:  v1.7.12
RuntimeApiVersion:  v1

[root@rocky9-2 ~]# crictl info
{
  "status": {
    "conditions": [
      {
        "type": "RuntimeReady",
        "status": true,
        "reason": "",
        "message": ""
      },
      {
        "type": "NetworkReady",
        "status": true,
        "reason": "",
        "message": ""
      }
    ]
  },
  "cniconfig": {
    "PluginDirs": [
      "/opt/cni/bin"
    ],
    "PluginConfDir": "/etc/cni/net.d",
    "PluginMaxConfNum": 1,
    "Prefix": "eth",
    "Networks": [
      {
        "Config": {
          "Name": "cni-loopback",
          "CNIVersion": "0.3.1",
          "Plugins": [
            {
              "Network": {
                "type": "loopback",
                "ipam": {},
                "dns": {}
              },
              "Source": "{\"type\":\"loopback\"}"
            }
          ],
          "Source": "{\n\"cniVersion\": \"0.3.1\",\n\"name\": \"cni-loopback\",\n\"plugins\": [{\n  \"type\": \"loopback\"\n}]\n}"
        },
        "IFName": "lo"
      },
      {
        "Config": {
          "Name": "containerd-net",
          "CNIVersion": "1.0.0",
          "Plugins": [
            {
              "Network": {
                "type": "bridge",
                "ipam": {
                  "type": "host-local"
                },
                "dns": {}
              },
              "Source": "{\"bridge\":\"cni0\",\"ipMasq\":true,\"ipam\":{\"ranges\":[[{\"subnet\":\"10.88.0.0/16\"}],[{\"subnet\":\"2001:4860:4860::/64\"}]],\"routes\":[{\"dst\":\"0.0.0.0/0\"},{\"dst\":\"::/0\"}],\"type\":\"host-local\"},\"isGateway\":true,\"promiscMode\":true,\"type\":\"bridge\"}"
            },
            {
              "Network": {
                "type": "portmap",
                "capabilities": {
                  "portMappings": true
                },
                "ipam": {},
                "dns": {}
              },
              "Source": "{\"capabilities\":{\"portMappings\":true},\"type\":\"portmap\"}"
            }
          ],
          "Source": "{\n  \"cniVersion\": \"1.0.0\",\n  \"name\": \"containerd-net\",\n  \"plugins\": [\n    {\n      \"type\": \"bridge\",\n      \"bridge\": \"cni0\",\n      \"isGateway\": true,\n      \"ipMasq\": true,\n      \"promiscMode\": true,\n      \"ipam\": {\n        \"type\": \"host-local\",\n        \"ranges\": [\n          [{\n            \"subnet\": \"10.88.0.0/16\"\n          }],\n          [{\n            \"subnet\": \"2001:4860:4860::/64\"\n          }]\n        ],\n        \"routes\": [\n          { \"dst\": \"0.0.0.0/0\" },\n          { \"dst\": \"::/0\" }\n        ]\n      }\n    },\n    {\n      \"type\": \"portmap\",\n      \"capabilities\": {\"portMappings\": true}\n    }\n  ]\n}\n"
        },
        "IFName": "eth0"
      }
    ]
  },
  "config": {
    "containerd": {
      "snapshotter": "overlayfs",
      "defaultRuntimeName": "runc",
      "defaultRuntime": {
        "runtimeType": "",
        "runtimePath": "",
        "runtimeEngine": "",
        "PodAnnotations": [],
        "ContainerAnnotations": [],
        "runtimeRoot": "",
        "options": {},
        "privileged_without_host_devices": false,
        "privileged_without_host_devices_all_devices_allowed": false,
        "baseRuntimeSpec": "",
        "cniConfDir": "",
        "cniMaxConfNum": 0,
        "snapshotter": "",
        "sandboxMode": ""
      },
      "untrustedWorkloadRuntime": {
        "runtimeType": "",
        "runtimePath": "",
        "runtimeEngine": "",
        "PodAnnotations": [],
        "ContainerAnnotations": [],
        "runtimeRoot": "",
        "options": {},
        "privileged_without_host_devices": false,
        "privileged_without_host_devices_all_devices_allowed": false,
        "baseRuntimeSpec": "",
        "cniConfDir": "",
        "cniMaxConfNum": 0,
        "snapshotter": "",
        "sandboxMode": ""
      },
      "runtimes": {
        "runc": {
          "runtimeType": "io.containerd.runc.v2",
          "runtimePath": "",
          "runtimeEngine": "",
          "PodAnnotations": [],
          "ContainerAnnotations": [],
          "runtimeRoot": "",
          "options": {
            "BinaryName": "",
            "CriuImagePath": "",
            "CriuPath": "",
            "CriuWorkPath": "",
            "IoGid": 0,
            "IoUid": 0,
            "NoNewKeyring": false,
            "NoPivotRoot": false,
            "Root": "",
            "ShimCgroup": "",
            "SystemdCgroup": true
          },
          "privileged_without_host_devices": false,
          "privileged_without_host_devices_all_devices_allowed": false,
          "baseRuntimeSpec": "",
          "cniConfDir": "",
          "cniMaxConfNum": 0,
          "snapshotter": "",
          "sandboxMode": "podsandbox"
        }
      },
      "noPivot": false,
      "disableSnapshotAnnotations": true,
      "discardUnpackedLayers": false,
      "ignoreBlockIONotEnabledErrors": false,
      "ignoreRdtNotEnabledErrors": false
    },
    "cni": {
      "binDir": "/opt/cni/bin",
      "confDir": "/etc/cni/net.d",
      "maxConfNum": 1,
      "setupSerially": false,
      "confTemplate": "",
      "ipPref": ""
    },
    "registry": {
      "configPath": "",
      "mirrors": {
        "docker.io": {
          "endpoint": [
            "https://registry.docker-cn.com",
            "https://hub-mirror.c.163.com",
            "https://docker.mirrors.ustc.edu.cn"
          ]
        }
      },
      "configs": {},
      "auths": {},
      "headers": {}
    },
    "imageDecryption": {
      "keyModel": "node"
    },
    "disableTCPService": true,
    "streamServerAddress": "127.0.0.1",
    "streamServerPort": "0",
    "streamIdleTimeout": "4h0m0s",
    "enableSelinux": false,
    "selinuxCategoryRange": 1024,
    "sandboxImage": "registry.aliyuncs.com/google_containers/pause:3.8",
    "statsCollectPeriod": 10,
    "systemdCgroup": false,
    "enableTLSStreaming": false,
    "x509KeyPairStreaming": {
      "tlsCertFile": "",
      "tlsKeyFile": ""
    },
    "maxContainerLogSize": 16384,
    "disableCgroup": false,
    "disableApparmor": false,
    "restrictOOMScoreAdj": false,
    "maxConcurrentDownloads": 3,
    "disableProcMount": false,
    "unsetSeccompProfile": "",
    "tolerateMissingHugetlbController": true,
    "disableHugetlbController": true,
    "device_ownership_from_security_context": false,
    "ignoreImageDefinedVolumes": false,
    "netnsMountsUnderStateDir": false,
    "enableUnprivilegedPorts": false,
    "enableUnprivilegedICMP": false,
    "enableCDI": false,
    "cdiSpecDirs": [
      "/etc/cdi",
      "/var/run/cdi"
    ],
    "imagePullProgressTimeout": "5m0s",
    "drainExecSyncIOTimeout": "0s",
    "containerdRootDir": "/var/lib/containerd",
    "containerdEndpoint": "/run/containerd/containerd.sock",
    "rootDir": "/var/lib/containerd/io.containerd.grpc.v1.cri",
    "stateDir": "/run/containerd/io.containerd.grpc.v1.cri"
  },
  "golang": "go1.20.13",
  "lastCNILoadStatus": "OK",
  "lastCNILoadStatus.default": "OK"
}

2.2.4 containerd 客户端工具 nerdctl

推荐使用 nerdctl,使用效果与 docker 命令的语法一致,github 下载链接:

https://github.com/containerd/nerdctl/releases

  • 精简 (nerdctl–linux-amd64.tar.gz): 只包含 nerdctl
  • 完整 (nerdctl-full–linux-amd64.tar.gz): 包含 containerd, runc, and CNI 等依赖

nerdctl 的目标并不是单纯地复制 docker 的功能,它还实现了很多 docker 不具备的功能,例如延迟拉取镜像(lazy-pulling)、镜像加密(imgcrypt)等。具体看 nerdctl。

t1-3

延迟拉取镜像功能可以参考这篇文章:Containerd 使用 Stargz Snapshotter 延迟拉取镜像

https://icloudnative.io/posts/startup-containers-in-lightning-speed-with-lazy-image-distribution-on-containerd/

1)安装 nerdctl(精简版):

[root@rocky9 ~]#  wget https://github.com/containerd/nerdctl/releases/download/v1.7.3/nerdctl-1.7.3-linux-amd64.tar.gz

[root@rocky9 ~]# tar xf nerdctl-1.7.3-linux-amd64.tar.gz -C /usr/local/bin/

# 配置nerdctl
cat > /etc/nerdctl/nerdctl.toml <<EOF
namespace      = "default"
insecure_registry = true
EOF

[root@rocky9 ~]# cat /etc/nerdctl/nerdctl.toml 
namespace      = "default" # 设置nerdctl工具默认namespace
insecure_registry = true # 跳过安全镜像仓库检测

2)安装 buildkit 支持构建镜像:

buildkit GitHub 地址:

https://github.com/moby/buildkit

使用精简版 nerdctl 无法直接通过 containerd 构建镜像,需要与 buildkit 组全使用以实现镜像构建。当然你也可以安装上面的完整 nerdctl;buildkit 项目是 Docker 公司开源出来的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:

  • 服务端 buildkitd,当前支持 runc 和 containerd 作为 worker,默认是 runc;
  • 客户端 buildctl,负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求。

buildkit 是典型的C/S 架构,client 和 server 可以不在一台服务器上。而 nerdctl 在构建镜像方面也可以作为 buildkitd 的客户端。

[root@rocky9 ~]# wget https://github.com/moby/buildkit/releases/download/v0.12.5/buildkit-v0.12.5.linux-amd64.tar.gz

[root@rocky9 ~]# tar xf buildkit-v0.12.5.linux-amd64.tar.gz -C /usr/local/

配置 buildkit 的启动文件,可以从这里下载:

https://github.com/moby/buildkit/tree/master/examples/systemd

buildkit 需要配置两个文件

  • /usr/lib/systemd/system/buildkit.socket

    [root@rocky9 ~]# cat > /usr/lib/systemd/system/buildkit.socket <<EOF
    [Unit]
    Description=BuildKit
    Documentation=https://github.com/moby/buildkit
    
    [Socket]
    ListenStream=%t/buildkit/buildkitd.sock
    SocketMode=0660
    
    [Install]
    WantedBy=sockets.target
    EOF
    
  • /usr/lib/systemd/system/buildkit.service

    [root@rocky9 ~]# cat > /usr/lib/systemd/system/buildkit.service << EOF
    [Unit]
    Description=BuildKit
    Requires=buildkit.socket
    After=buildkit.socket
    Documentation=https://github.com/moby/buildkit
    
    [Service]
    Type=notify
    ExecStart=/usr/local/bin/buildkitd --addr fd://
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

启动 buildkit:

[root@rocky9 ~]# systemctl daemon-reload && systemctl enable --now buildkit 

[root@rocky9 ~]# systemctl status buildkit
● buildkit.service - BuildKit
     Loaded: loaded (/usr/lib/systemd/system/buildkit.service; enabled; preset: disabled)
     Active: active (running) since Thu 2024-02-01 21:33:36 CST; 22s ago
TriggeredBy: ● buildkit.socket
       Docs: https://github.com/moby/buildkit
   Main PID: 15218 (buildkitd)
      Tasks: 9 (limit: 10840)
     Memory: 13.7M
        CPU: 36ms
     CGroup: /system.slice/buildkit.service
             └─15218 /usr/local/bin/buildkitd --addr fd://

Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=warning msg="using host network as the >
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=warning msg="git source cannot be enabl>
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=info msg="found worker \"qc0w0cvit1te4m>
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=warning msg="using host network as the >
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=warning msg="git source cannot be enabl>
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=info msg="found worker \"8e8fqp2ogv0ipy>
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=info msg="found 2 workers, default=\"qc>
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=warning msg="currently, only the defaul>
Feb 01 21:33:36 rocky9 systemd[1]: Started BuildKit.
Feb 01 21:33:36 rocky9 buildkitd[15218]: time="2024-02-01T21:33:36+08:00" level=info msg="running server on /run/buildk>

[root@rocky9 ~]# nerdctl version
Client:
 Version:	v1.7.3
 OS/Arch:	linux/amd64
 Git commit:	0a464409d0178e16d3d2bed36222937ec3fc9c77
 buildctl:
  Version:	v0.12.5
  GitCommit:	bac3f2b673f3f9d33e79046008e7a38e856b3dc6

Server:
 containerd:
  Version:	v1.7.10
  GitCommit:	4e1fe7492b9df85914c389d1f15a3ceedbb280ac
 runc:
  Version:	1.1.10
  GitCommit:	v1.1.10-0-g18a0cb0f

[root@rocky9 ~]# nerdctl info
Client:
 Namespace:	default
 Debug Mode:	false

Server:
 Server Version: v1.7.10
 Storage Driver: overlayfs
 Logging Driver: json-file
 Cgroup Driver: systemd
 Cgroup Version: 2
 Plugins:
  Log: fluentd journald json-file syslog
  Storage: native overlayfs
 Security Options:
  seccomp
   Profile: builtin
  cgroupns
 Kernel Version: 5.14.0-362.8.1.el9_3.x86_64
 Operating System: Rocky Linux 9.3 (Blue Onyx)
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 1.692GiB
 Name: rocky9
 ID: b17950f1-e38a-4ec8-9857-21a7d572eae7

解决"WARNING: No swap limit support"报警提示:

# SWAP报警提示,只有在ubuntu 20.04和18.04里面有
root@ubuntu2004:~# sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ swapaccount=1"@' /etc/default/grub

root@ubuntu2004:~# update-grub
root@ubuntu2004:~# reboot

root@ubuntu2004:~# nerdctl info
Client:
 Namespace:	default
 Debug Mode:	false

Server:
 Server Version: v1.6.8
 Storage Driver: overlayfs
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Log: fluentd journald json-file
  Storage: aufs native overlayfs
 Security Options:
  apparmor
  seccomp
   Profile: default
 Kernel Version: 5.4.0-125-generic
 Operating System: Ubuntu 20.04.4 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.81GiB
 Name: k8s-master01.example.local
 ID: ab901e55-fa37-496e-9920-ee6eff687687
#现在就没有SWAP报警提示

2.2.5 一键安装containerd脚本

Shell脚本源码地址:

Gitee:https://gitee.com/raymond9/shell

Github:https://github.com/raymond999999/shell

可以去上面的Gitee或Github代码仓库拉取脚本。

2.2.5.1 基于镜像仓库一键安装containerd脚本
[root@rocky9 ~]# cat install_containerd.sh
#!/bin/bash
#
#*************************************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2024-02-15
#FileName:      install_containerd.sh
#URL:           raymond.blog.csdn.net
#Description:   install_containerd for CentOS 7 & CentOS Stream 8/9 & Ubuntu 18.04/20.04/22.04 & Rocky 8/9
#Copyright (C): 2024 All rights reserved
#*************************************************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'
CONTAINERD_VERSION=1.6.28
URL='mirrors.aliyun.com'

#crictl下载地址:“https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz”,请提前下载。
CRICTL_FILE=crictl-v1.29.0-linux-amd64.tar.gz
#CNIl下载地址:“https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz”,请提前下载。
CNI_FILE=cni-plugins-linux-amd64-v1.4.0.tgz
#Netdctl下载地址:“https://github.com/containerd/nerdctl/releases/download/v1.7.3/nerdctl-1.7.3-linux-amd64.tar.gz”,请提前下载。
NETDCTL_FILE=nerdctl-1.7.3-linux-amd64.tar.gz
#Buildkit下载地址:“https://github.com/moby/buildkit/releases/download/v0.12.5/buildkit-v0.12.5.linux-amd64.tar.gz”,请提前下载。
BUILDKIT_FILE=buildkit-v0.12.5.linux-amd64.tar.gz

os(){
    OS_ID=`sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release`
    OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.*="?([0-9]+)\.?.*"?@\1@p' /etc/os-release`
}

check_file(){
    cd ${SRC_DIR}
    if [ ! -e ${CRICTL_FILE} ];then
        ${COLOR}"缺少${CRICTL_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    elif [ ! -e ${CNI_FILE} ];then
        ${COLOR}"缺少${CNI_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    elif [ ! -e ${NETDCTL_FILE} ];then
        ${COLOR}"缺少${NETDCTL_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    elif [ ! -e ${BUILDKIT_FILE} ];then
        ${COLOR}"缺少${BUILDKIT_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    else
        ${COLOR}"相关文件已准备好"${END}
    fi
}

set_kernel(){
    cat > /etc/modules-load.d/containerd.conf <<-EOF
overlay
br_netfilter
EOF
    modprobe -- overlay
    modprobe -- br_netfilter

    cat > /etc/sysctl.d/99-kubernetes-cri.conf <<-EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
    sysctl --system &> /dev/null
}

ubuntu_install_docker(){
    dpkg -s containerd &>/dev/null && ${COLOR}"Containerd已安装,退出"${END} && exit
    ${COLOR}"开始安装Containerd依赖包,请稍等..."${END}
    apt update &> /dev/null
    apt -y install apt-transport-https ca-certificates curl software-properties-common &> /dev/null
    curl -fsSL https://${URL}/docker-ce/linux/ubuntu/gpg | sudo apt-key add - &> /dev/null
    add-apt-repository -y "deb [arch=amd64] https://${URL}/docker-ce/linux/ubuntu  $(lsb_release -cs) stable" &> /dev/null 
    apt update &> /dev/null

    ${COLOR}"Containerd有以下版本"${END}
    apt-cache madison containerd.io
    ${COLOR}"10秒后即将安装:Containerd-"${CONTAINERD_VERSION}"版本......"${END}
    ${COLOR}"如果想安装其它Containerd版本,请按Ctrl+c键退出,修改版本再执行"${END}
    sleep 10

    ${COLOR}"开始安装Containerd,请稍等..."${END}
    apt -y install containerd.io=${CONTAINERD_VERSION}-1 &> /dev/null || { ${COLOR}"apt源失败,请检查apt配置"${END};exit; }
}

centos_install_docker(){
    rpm -q containerd &> /dev/null && ${COLOR}"Containerd已安装,退出"${END} && exit
    ${COLOR}"开始安装Containerd依赖包,请稍等..."${END}
    yum -y install yum-utils &> /dev/null
    yum-config-manager --add-repo https://${URL}/docker-ce/linux/centos/docker-ce.repo &> /dev/null
    yum clean all &> /dev/null
	yum makecache &> /dev/null

    ${COLOR}"Containerd有以下版本"${END}
    yum list containerd.io --showduplicates
    ${COLOR}"10秒后即将安装:Containerd-"${CONTAINERD_VERSION}"版本......"${END}
    ${COLOR}"如果想安装其它Containerd版本,请按Ctrl+c键退出,修改版本再执行"${END}
    sleep 10

    ${COLOR}"开始安装Containerd,请稍等..."${END}
    yum -y install containerd.io-${CONTAINERD_VERSION} &> /dev/null || { ${COLOR}"yum源失败,请检查yum配置"${END};exit; }
}

config_containerd(){
    mkdir -p /etc/containerd
    containerd config default | tee /etc/containerd/config.toml &> /dev/null 
    sed -ri -e 's/(.*SystemdCgroup = ).*/\1true/' -e "s#registry.k8s.io#registry.aliyuncs.com/google_containers#g" /etc/containerd/config.toml
    sed -i '/.*registry.mirrors.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]' /etc/containerd/config.toml
}

set_alias(){
    echo 'alias rmi="nerdctl images -qa|xargs nerdctl rmi -f"' >> ~/.bashrc
    echo 'alias rmc="nerdctl ps -qa|xargs nerdctl rm -f"' >> ~/.bashrc
}

install_crictl_cni(){
    ${COLOR}"开始安装Crictl工具,请稍等..."${END}
    tar xf ${CRICTL_FILE} -C /usr/local/bin
    cat > /etc/crictl.yaml <<-EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

    ${COLOR}"开始安装CNI插件,请稍等..."${END}
    mkdir -p /opt/cni/bin/
    tar xf ${CNI_FILE} -C /opt/cni/bin/
    mkdir -p /etc/cni/net.d/
    cat > /etc/cni/net.d/10-containerd-net.conflist <<EOF
{
  "cniVersion": "1.0.0",
  "name": "containerd-net",
  "plugins": [
    {
      "type": "bridge",
      "bridge": "cni0",
      "isGateway": true,
      "ipMasq": true,
      "promiscMode": true,
      "ipam": {
        "type": "host-local",
        "ranges": [
          [{
            "subnet": "10.88.0.0/16"
          }],
          [{
            "subnet": "2001:4860:4860::/64"
          }]
        ],
        "routes": [
          { "dst": "0.0.0.0/0" },
          { "dst": "::/0" }
        ]
      }
    },
    {
      "type": "portmap",
      "capabilities": {"portMappings": true}
    }
  ]
}
EOF

    systemctl daemon-reload && systemctl enable --now containerd &> /dev/null
    systemctl restart containerd
    systemctl is-active containerd &> /dev/null && ${COLOR}"Containerd 服务启动成功"${END} || { ${COLOR}"Containerd 启动失败"${END};exit; }
    ctr version &&  ${COLOR}"Containerd 安装成功"${END} || ${COLOR}"Containerd 安装失败"${END}    
}

install_netdctl_buildkit(){
    ${COLOR}"开始安装Netdctl..."${END}
    tar xf ${NETDCTL_FILE} -C /usr/local/bin/
    mkdir -p /etc/nerdctl/
    cat > /etc/nerdctl/nerdctl.toml <<EOF
namespace      = "default"
insecure_registry = true
EOF

    ${COLOR}"开始安装Buildkit..."${END}
    tar xf ${BUILDKIT_FILE} -C /usr/local/
    cat > /usr/lib/systemd/system/buildkit.socket <<-EOF
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

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

[Install]
WantedBy=sockets.target
EOF
    cat > /usr/lib/systemd/system/buildkit.service <<-EOF
[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentation=https://github.com/moby/buildkit

[Service]
Type=notify
ExecStart=/usr/local/bin/buildkitd --addr fd://

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload && systemctl enable --now buildkit &> /dev/null
    systemctl is-active buildkit &> /dev/null && ${COLOR}"Buildkit 服务启动成功"${END} || { ${COLOR}"Buildkit 启动失败"${END};exit; }
    buildctl --version &&  ${COLOR}"Buildkit 安装成功"${END} || ${COLOR}"Buildkit 安装失败"${END}
}

set_swap_limit(){
    if [ ${OS_RELEASE_VERSION} == "18" -o ${OS_RELEASE_VERSION} == "20" ];then
        grep -q "swapaccount=1" /etc/default/grub && { ${COLOR}'"WARNING: No swap limit support"警告,已设置'${END};exit; }
        ${COLOR}'设置Docker的"WARNING: No swap limit support"警告'${END}
        sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ swapaccount=1"@' /etc/default/grub
        update-grub &> /dev/null
        ${COLOR}"10秒后,机器会自动重启!"${END}
        sleep 10
        reboot
    fi
}

main(){
    os
    check_file
    set_kernel
    if [ ${OS_ID} == "CentOS" -o ${OS_ID} == "Rocky" ] &> /dev/null;then
        centos_install_docker
    else
        ubuntu_install_docker
    fi
    config_containerd
    set_alias
    install_crictl_cni
    install_netdctl_buildkit
    set_swap_limit
}

main
2.2.5.2 基于二进制包一键安装containerd脚本
[root@rocky9-2 ~]# cat install_containerd_binary.sh
#!/bin/bash
#
#******************************************************************************************************************
#Author:        Raymond
#QQ:            88563128
#Date:          2024-02-15
#FileName:      install_containerd_binary.sh
#URL:           raymond.blog.csdn.net
#Description:   install_containerd_binary CentOS 7 & CentOS Stream 8/9 & Ubuntu 18.04/20.04/22.04 & Rocky 8/9
#Copyright (C): 2024 All rights reserved
#******************************************************************************************************************
SRC_DIR=/usr/local/src
COLOR="echo -e \\033[01;31m"
END='\033[0m'

#Containerd下载地址:“https://github.com/containerd/containerd/releases/download/v1.7.12/cri-containerd-cni-1.7.12-linux-amd64.tar.gz”,请提前下载。
CONTAINERD_FILE=cri-containerd-cni-1.7.12-linux-amd64.tar.gz

#Netdctl下载地址:“https://github.com/containerd/nerdctl/releases/download/v1.7.3/nerdctl-1.7.3-linux-amd64.tar.gz”,请提前下载。
NETDCTL_FILE=nerdctl-1.7.3-linux-amd64.tar.gz
#Buildkit下载地址:“https://github.com/moby/buildkit/releases/download/v0.12.5/buildkit-v0.12.5.linux-amd64.tar.gz”,请提前下载。
BUILDKIT_FILE=buildkit-v0.12.5.linux-amd64.tar.gz

os(){
    OS_ID=`sed -rn '/^NAME=/s@.*="([[:alpha:]]+).*"$@\1@p' /etc/os-release`
    OS_RELEASE_VERSION=`sed -rn '/^VERSION_ID=/s@.*="?([0-9]+)\.?.*"?@\1@p' /etc/os-release`
}

check_file (){
    cd ${SRC_DIR}
    if [ ! -e ${CONTAINERD_FILE} ];then
        ${COLOR}"缺少${CONTAINERD_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    elif [ ! -e ${NETDCTL_FILE} ];then
        ${COLOR}"缺少${NETDCTL_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    elif [ ! -e ${BUILDKIT_FILE} ];then
        ${COLOR}"缺少${BUILDKIT_FILE}文件,请把文件放到${SRC_DIR}目录下"${END}
        exit
    else
        ${COLOR}"相关文件已准备好"${END}
    fi
}

install_containerd(){ 
    [ -f /usr/local/bin/containerd ] && { ${COLOR}"Containerd已存在,安装失败"${END};exit; }
    cat > /etc/modules-load.d/containerd.conf <<-EOF
overlay
br_netfilter
EOF
    modprobe -- overlay
    modprobe -- br_netfilter

    cat > /etc/sysctl.d/99-kubernetes-cri.conf <<-EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
    sysctl --system &> /dev/null

    ${COLOR}"开始安装Containerd..."${END}
    tar xf ${CONTAINERD_FILE} -C /

    mkdir -p /etc/containerd
    containerd config default | tee /etc/containerd/config.toml &> /dev/null 
    sed -ri -e 's/(.*SystemdCgroup = ).*/\1true/' -e "s#registry.k8s.io#registry.aliyuncs.com/google_containers#g" /etc/containerd/config.toml
    sed -i '/.*registry.mirrors.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]\n          endpoint = ["https://registry.docker-cn.com" ,"https://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"]' /etc/containerd/config.toml
    cat > /etc/crictl.yaml <<-EOF
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
    systemctl daemon-reload && systemctl enable --now containerd &> /dev/null
    systemctl is-active containerd &> /dev/null && ${COLOR}"Containerd 服务启动成功"${END} || { ${COLOR}"Containerd 启动失败"${END};exit; }
    ctr version &&  ${COLOR}"Containerd 安装成功"${END} || ${COLOR}"Containerd 安装失败"${END}
}

set_alias(){
    echo 'alias rmi="nerdctl images -qa|xargs nerdctl rmi -f"' >> ~/.bashrc
    echo 'alias rmc="nerdctl ps -qa|xargs nerdctl rm -f"' >> ~/.bashrc
}

install_netdctl_buildkit(){
    ${COLOR}"开始安装Netdctl..."${END}
    tar xf ${NETDCTL_FILE} -C /usr/local/bin/
    mkdir -p /etc/nerdctl/
    cat > /etc/nerdctl/nerdctl.toml <<EOF
namespace      = "default"
insecure_registry = true
EOF

    ${COLOR}"开始安装Buildkit..."${END}
    tar xf ${BUILDKIT_FILE} -C /usr/local/
    cat > /usr/lib/systemd/system/buildkit.socket <<-EOF
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

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

[Install]
WantedBy=sockets.target
EOF
    cat > /usr/lib/systemd/system/buildkit.service <<-EOF
[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentation=https://github.com/moby/buildkit

[Service]
Type=notify
ExecStart=/usr/local/bin/buildkitd --addr fd://

[Install]
WantedBy=multi-user.target
EOF
    systemctl daemon-reload && systemctl enable --now buildkit &> /dev/null
    systemctl is-active buildkit &> /dev/null && ${COLOR}"Buildkit 服务启动成功"${END} || { ${COLOR}"Buildkit 启动失败"${END};exit; }
    buildctl --version &&  ${COLOR}"Buildkit 安装成功"${END} || ${COLOR}"Buildkit 安装失败"${END}
}

set_swap_limit(){
    if [ ${OS_RELEASE_VERSION} == "18" -o ${OS_RELEASE_VERSION} == "20" ];then
        grep -q "swapaccount=1" /etc/default/grub && { ${COLOR}'"WARNING: No swap limit support"警告,已设置'${END};exit; }
        ${COLOR}'设置Docker的"WARNING: No swap limit support"警告'${END}
        sed -ri '/^GRUB_CMDLINE_LINUX=/s@"$@ swapaccount=1"@' /etc/default/grub
        update-grub &> /dev/null
        ${COLOR}"10秒后,机器会自动重启"${END}
        sleep 10
        reboot
    fi
}

main(){
    os
    check_file
    install_containerd
    set_alias
    install_netdctl_buildkit
    set_swap_limit
}

main

2.2.6 Containerd 常见命令操作

更换 Containerd 后,以往我们常用的 docker 命令也不再使用,取而代之的分别是 crictlctr 两个命令客户端。

  • crictl 是遵循 CRI 接口规范的一个命令行工具,通常用它来检查和管理容器运行时和镜像。
  • ctrcontainerd 的一个客户端工具。
  • ctr -v 输出的是 containerd 的版本,crictl -v 输出的是crictl的版本。
命令dockerctr(containerd)crictl(kubernetes)
查看运行的容器docker psctr task ls/ctr container lscrictl ps
查看镜像docker imagesctr image lscrictl images
查看容器日志docker logscrictl logs
查看容器数据信息docker inspectctr container infocrictl inspect
查看容器资源docker statscrictl stats
启动/关闭已有的容器docker start/stopctr task start/killcrictl start/stop
运行一个新的容器docker runctr run无(最小单元为 pod)
打标签docker tagctr image tag
创建一个新的容器docker createctr container createcrictl create
导入镜像docker loadctr image import
导出镜像docker savectr image export
删除容器docker rmctr container rmcrictl rm
删除镜像docker rmictr image rmcrictl rmi
拉取镜像docker pullctr image pullctictl pull
推送镜像docker pushctr image push
登录或在容器内部执行命令docker execcrictl exec
清空不用的容器docker image prunecrictl rmi --prune

更多命令操作,可以直接在命令行输入命令查看帮助。

docker --help
ctr --help
crictl --help

由于 Containerd 也有 namespaces 的概念,对于上层编排系统的支持,ctr 客户端 主要区分了 3 个命名空间分别是k8s.iomobydefault,以上我们用crictl操作的均在k8s.io命名空间,使用ctr 看镜像列表就需要加上-n 参数。crictl 是只有一个k8s.io命名空间,但是没有-n 参数。

【温馨提示】ctr images pull 拉取的镜像默认放在default,而 crictl pull 和 kubelet 默认拉取的镜像都在 k8s.io 命名空间下。所以通过ctr导入镜像的时候特别注意一点,最好指定命名空间。

2.2.6.1 ctr命令使用
# --address value, -a value 指定 containerd's GRPC server,默认 /run/containerd/containerd.sock

# 下载镜像
[root@rocky9 ~]# ctr images pull docker.io/library/redis:alpine

# 创建 container
[root@rocky9 ~]# ctr container create docker.io/library/redis:alpine redis-container

# 查看
[root@rocky9 ~]# ctr container ls
CONTAINER          IMAGE                             RUNTIME                  
redis-container    docker.io/library/redis:alpine    io.containerd.runc.v2   

# 后台启动
[root@rocky9 ~]# ctr task start -d redis-container

# 查看 container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
redis-container    11741    RUNNING

# 暂停容器运行
[root@rocky9 ~]# ctr task pause redis-container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
redis-container    11741    PAUSED

# 恢复容器之前的状态
[root@rocky9 ~]# ctr task resume redis-container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
redis-container    11741    RUNNING

# 删除container
[root@rocky9 ~]# ctr task rm redis-container
ERRO[0000] unable to delete redis-container              error="task must be stopped before deletion: running: failed precondition"
ctr: task must be stopped before deletion: running: failed precondition
# 运行的容器删不了

# 停止容器运行
[root@rocky9 ~]# ctr task kill redis-container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
redis-container    11741    STOPPED
[root@rocky9 ~]# ctr task rm redis-container
[root@rocky9 ~]# ctr task ls
TASK    PID    STATUS
# 容器只有在STOPPED,状态才可以删除

[root@rocky9 ~]# ctr container ls
CONTAINER          IMAGE                             RUNTIME                  
redis-container    docker.io/library/redis:alpine    io.containerd.runc.v2    
[root@rocky9 ~]# ctr container rm redis-container
[root@rocky9 ~]# ctr container ls
CONTAINER    IMAGE    RUNTIME  
#现在才彻底删除

[root@rocky9 ~]# ctr images pull docker.io/library/nginx:1.24.0

[root@rocky9 ~]# ctr container create docker.io/library/nginx:1.24.0 nginx-container
[root@rocky9 ~]# ctr container create docker.io/library/redis:alpine redis-container
[root@rocky9 ~]# ctr container ls
CONTAINER          IMAGE                             RUNTIME                  
nginx-container    docker.io/library/nginx:1.21.6    io.containerd.runc.v2    
redis-container    docker.io/library/redis:alpine    io.containerd.runc.v2  

[root@rocky9 ~]# ctr task start -d nginx-container
[root@rocky9 ~]# ctr task start -d redis-container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
nginx-container    11977    RUNNING
redis-container    12052    RUNNING

[root@rocky9 ~]# ctr task kill nginx-container
[root@rocky9 ~]# ctr task kill redis-container
[root@rocky9 ~]# ctr task ls
TASK               PID      STATUS    
nginx-container    11977    STOPPED
redis-container    12052    STOPPED

[root@rocky9 ~]# ctr task rm nginx-container
[root@rocky9 ~]# ctr task rm redis-container
[root@rocky9 ~]# ctr task ls
TASK    PID    STATUS  

# 删除所有容器
[root@rocky9 ~]# ctr container ls
CONTAINER          IMAGE                             RUNTIME                  
nginx-container    docker.io/library/nginx:1.21.6    io.containerd.runc.v2    
redis-container    docker.io/library/redis:alpine    io.containerd.runc.v2    
[root@rocky9 ~]# ctr container ls| awk -F" " 'NR!=1{print $1}'| xargs ctr container rm
[root@rocky9 ~]# ctr container ls
CONTAINER    IMAGE    RUNTIME 

# 查看命名空间
[root@rocky9 ~]# ctr ns ls
NAME    LABELS 
default 

# 查看 k8s 中正在运行的容器
[root@k8s-master01 ~]# ctr -n k8s.io task ls

配置私有镜像仓库http:

参考文档:https://github.com/containerd/cri/blob/master/docs/registry.md

[root@rocky9 ~]# vim /etc/containerd/config.toml
# 下面几行是配置私有仓库授权,如果没有私有仓库下面的不用设置
      [plugins."io.containerd.grpc.v1.cri".registry.configs] # 在这行下面配置如下内容
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.raymonds.cc".tls]
          insecure_skip_verify = true
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.raymonds.cc".auth]
          username = "admin"
          password = "123456"
...
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://registry.docker-cn.com" ,"http://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"] # 在镜像加速后面配置下面配置
# 下面两行是配置私有仓库,如果没有私有仓库下面的不用设置
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.raymonds.cc"]
          endpoint = ["http://harbor.raymonds.cc"]

# 使用下面命令修改
HARBOR_DOMAIN=harbor.raymonds.cc
sed -i -e '/.*registry.configs.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.configs."'''${HARBOR_DOMAIN}'''".tls]\n          insecure_skip_verify = true\n        [plugins."io.containerd.grpc.v1.cri".registry.configs."'''${HARBOR_DOMAIN}'''".auth]\n          username = "admin"\n          password = "123456"' -e '/.*endpoint = \[.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."'''${HARBOR_DOMAIN}'''"]\n          endpoint = ["http://'''${HARBOR_DOMAIN}'''"]' /etc/containerd/config.toml

[root@rocky9 ~]# systemctl restart containerd

[root@rocky9 ~]# cat >> /etc/hosts <<-EOF
172.31.0.29 harbor.raymonds.cc
EOF

# 打tag
[root@rocky9 ~]# ctr images tag docker.io/library/redis:alpine  harbor.raymonds.cc/library/redis:alpine

# push 上传镜像
[root@rocky9 ~]# ctr images push harbor.raymonds.cc/library/redis:alpine
...
----------------| 
elapsed: 0.1 s                                                                    total:   0.0 B (0.0 B/s)                                         
ctr: content digest sha256:431588b12459ea98eb57981ee240f8b0ea161145ab554f0d0a01d0815f0d7789: not found
# 注意可能会出现 ctr: content digest sha256:xxxxxx  not found,解决办法,下载完整的

# 加“--all-platforms”参数就是下载完整的镜像
[root@rocky9 ~]# ctr image pull --all-platforms docker.io/library/redis:alpine

[root@rocky9 ~]# ctr images rm harbor.raymonds.cc/library/redis:alpine

[root@rocky9 ~]# ctr images tag docker.io/library/redis:alpine  harbor.raymonds.cc/library/redis:alpine

[root@rocky9 ~]# ctr images push harbor.raymonds.cc/library/redis:alpine
...
ctr: failed to do request: Head "https://harbor.raymonds.cc/v2/library/redis/blobs/sha256:4f2827d94ec4fb6ff6a50d848af6a28207148465857aca97ed2ff7020f118f42": dial tcp 172.31.0.19:443: connect: connection refused
#使用了非https认证的harbor

[root@rocky9 ~]# ctr images push --plain-http harbor.raymonds.cc/library/redis:alpine
...
ctr: push access denied, repository does not exist or may require authorization: authorization failed: no basic auth credentials
# 会出现ctr: no basic auth credentials

[root@rocky9 ~]# ctr images push --plain-http -u admin harbor.raymonds.cc/library/redis:alpine
Password:
#这样才能上传镜像

从harbor上可以看到镜像已经被下载

在这里插入图片描述

# 导出镜像
[root@rocky9 ~]# ctr images export redis.tar docker.io/library/redis:alpine

[root@rocky9 ~]# ctr images rm docker.io/library/redis:alpine

# 导入镜像
[root@rocky9 ~]# ctr images import redis.tar

[root@rocky9 ~]# ctr images ls -q |grep redis
docker.io/library/redis:alpine

# 查看本地镜像
[root@rocky9 ~]# ctr images list -q

# 删除所有镜像
[root@rocky9 ~]# ctr images list -q|xargs ctr images rm

[root@rocky9 ~]# ctr images list -q

# 从harbor拉取镜像到本地
[root@rocky9 ~]# ctr image pull --plain-http harbor.raymonds.cc/library/redis:alpine

[root@rocky9 ~]# ctr images ls -q
harbor.raymonds.cc/library/redis:alpine

2.2.7 nerdctl命令实战操作

配置私有镜像仓库https:

参考文档:https://github.com/containerd/cri/blob/master/docs/registry.md

[root@rocky9-2 ~]# DOMAIN=raymonds.cc
[root@rocky9-2 ~]# mkdir -pv /etc/containerd/certs.d/harbor.${DOMAIN}
mkdir: created directory '/etc/containerd/certs.d'
mkdir: created directory '/etc/containerd/certs.d/harbor.raymonds.cc'

[root@rocky9-4 ~]# DOMAIN=raymonds.cc
[root@rocky9-4 ~]# scp -r /apps/harbor/certs/{harbor.${DOMAIN}.cert,harbor.${DOMAIN}.key,ca.crt} 172.31.0.19:/etc/containerd/certs.d/harbor.${DOMAIN}


[root@rocky9-2 ~]# tree /etc/containerd/certs.d/
-bash: tree: command not found
[root@rocky9-2 ~]# dnf -y install tree

[root@rocky9-2 ~]# tree /etc/containerd/certs.d/harbor.raymonds.cc/
/etc/containerd/certs.d/harbor.raymonds.cc/
├── ca.crt
├── harbor.raymonds.cc.cert
└── harbor.raymonds.cc.key

0 directories, 3 files

[root@rocky9-2 ~]# vim /etc/containerd/config.toml
...
# 下面几行是配置私有仓库授权,如果没有私有仓库下面的不用设置
      [plugins."io.containerd.grpc.v1.cri".registry.configs] # 在这行下面配置如下内容
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.raymonds.cc".tls]
          ca_file = "/etc/containerd/certs.d/harbor.raymonds.cc/ca.crt"
          cert_file = "/etc/containerd/certs.d/harbor.raymonds.cc/harbor.raymonds.cc.cert"
          key_file = "/etc/containerd/certs.d/harbor.raymonds.cc/harbor.raymonds.cc.key"
        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.raymonds.cc".auth]
          username = "admin"
          password = "123456"
...
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://registry.docker-cn.com" ,"http://hub-mirror.c.163.com" ,"https://docker.mirrors.ustc.edu.cn"] # 在镜像加速后面配置下面配置
# 下面两行是配置私有仓库,如果没有私有仓库下面的不用设置
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.raymonds.cc"]
          endpoint = ["https://harbor.raymonds.cc"]

# 使用下面命令修改
sed -i -e '/.*registry.configs.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.'''${DOMAIN}'''".tls]\n          ca_file = "/etc/containerd/certs.d/harbor.'''${DOMAIN}'''/ca.crt"\n          cert_file = "/etc/containerd/certs.d/harbor.'''${DOMAIN}'''/harbor.'''${DOMAIN}'''.cert"\n          key_file = "/etc/containerd/certs.d/harbor.'''${DOMAIN}'''/harbor.'''${DOMAIN}'''.key"\n        [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.'''${DOMAIN}'''".auth]\n          username = "admin"\n          password = "123456"' -e '/.*endpoint = \[.*/a\        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.'''${DOMAIN}'''"]\n          endpoint = ["https://harbor.'''${DOMAIN}'''"]' /etc/containerd/config.toml

[root@rocky9-2 ~]# systemctl restart containerd

[root@rocky9-2 ~]# cat >> /etc/hosts <<-EOF
172.31.0.39 harbor.raymonds.cc
EOF

1)拉取推送镜像

[root@rocky9-2 ~]# nerdctl pull redis:alpine

[root@rocky9-2 ~]# nerdctl images
REPOSITORY    TAG       IMAGE ID        CREATED          PLATFORM       SIZE        BLOB SIZE
redis         alpine    1b503bb77079    2 seconds ago    linux/amd64    41.4 MiB    16.0 MiB

[root@rocky9-2 ~]# nerdctl tag redis:alpine  harbor.raymonds.cc/library/redis:alpine
[root@rocky9-2 ~]# nerdctl images
REPOSITORY                          TAG       IMAGE ID        CREATED               PLATFORM       SIZE        BLOB SIZE
redis                               alpine    1b503bb77079    About a minute ago    linux/amd64    41.4 MiB    16.0 MiB
harbor.raymonds.cc/library/redis    alpine    1b503bb77079    2 seconds ago         linux/amd64    41.4 MiB    16.0 MiB

# 通过 nerdctl 登录 harbor
[root@rocky9-2 ~]# nerdctl login harbor.raymonds.cc
Enter Username: admin
Enter Password: 
WARN[0004] skipping verifying HTTPS certs for "harbor.raymonds.cc" 
WARNING: Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

[root@rocky9-2 ~]# nerdctl push harbor.raymonds.cc/library/redis:alpine

登录harbor可以看到镜像已经被推送到镜像仓库了。

t1-5

[root@rocky9-2 ~]# nerdctl images -qa|xargs nerdctl rmi -f

[root@rocky9-2 ~]# nerdctl pull harbor.raymonds.cc/library/redis:alpine

[root@rocky9-2 ~]# nerdctl images
REPOSITORY                          TAG       IMAGE ID        CREATED           PLATFORM       SIZE        BLOB SIZE
harbor.raymonds.cc/library/redis    alpine    c476327f7a62    50 seconds ago    linux/amd64    41.4 MiB    16.0 MiB

2)镜像构建

[root@rocky9-2 ~]# cat > Dockerfile <<EOF
FROM nginx:alpine
RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html
EOF

然后在文件所在目录执行镜像构建命令:

# 不加-n指定命名空间,crictl看不到,kubelet也不能使用它,默认在default命名空间下
nerdctl build -t nginx:nerctl -f ./Dockerfile .
### 参数解释
# -t:指定镜像名称
# . :当前目录Dockerfile
# -f:指定Dockerfile路径
#  --no-cache:不缓存

[root@rocky9-2 ~]# nerdctl build -t nginx:nerctl -f ./Dockerfile .
[+] Building 30.9s (6/6) FINISHED                                                                                       
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 131B                                                                               0.0s
 => [internal] load metadata for docker.io/library/nginx:alpine                                                    5.9s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [1/2] FROM docker.io/library/nginx:alpine@sha256:cedce0b6e276efe62bbf15345053f44cdc5d1c834a63ab7619aa8355093  18.5s
 => => resolve docker.io/library/nginx:alpine@sha256:cedce0b6e276efe62bbf15345053f44cdc5d1c834a63ab7619aa8355093f  0.0s
 => => sha256:a85ccd8c07bd7090e8a37ab878413b035a370e872367b145a0c0aaaaf60ccbdf 12.65MB / 12.65MB                  12.3s
 => => sha256:e1c681003a03fff277ecf90fccf526881bcc2e006c9e371b58f45680d54c1954 1.40kB / 1.40kB                     3.7s
 => => sha256:d6a456492aaa4c003389fec3da0939f31c505232fcf1925db314815a196c444f 1.21kB / 1.21kB                     3.7s
 => => sha256:a101c9a82b88a3fa561030af162d98a130ca3bc0501b2e70594410dd426f2c9b 393B / 393B                         3.7s
 => => sha256:c3ea3344e711fd7111dee02f17deebceb725ed1d0ee998f7fb472114dc1399ce 629B / 629B                         1.7s
 => => sha256:018b9065ed0dfedff48bbd11f6014960bb496e71c395f772bfad123ab33a1800 1.90MB / 1.90MB                     9.8s
 => => sha256:619be1103602d98e1963557998c954c892b3872986c27365e9f651f5bc27cab8 3.40MB / 3.40MB                    13.6s
 => => sha256:c7059f3102784cd05dc96fff74a52bce9fa50fea724ece08748507fa3455999b 956B / 956B                         2.6s
 => => extracting sha256:619be1103602d98e1963557998c954c892b3872986c27365e9f651f5bc27cab8                          0.2s
 => => extracting sha256:018b9065ed0dfedff48bbd11f6014960bb496e71c395f772bfad123ab33a1800                          0.3s
 => => extracting sha256:c3ea3344e711fd7111dee02f17deebceb725ed1d0ee998f7fb472114dc1399ce                          0.0s
 => => extracting sha256:c7059f3102784cd05dc96fff74a52bce9fa50fea724ece08748507fa3455999b                          0.0s
 => => extracting sha256:a101c9a82b88a3fa561030af162d98a130ca3bc0501b2e70594410dd426f2c9b                          0.0s
 => => extracting sha256:d6a456492aaa4c003389fec3da0939f31c505232fcf1925db314815a196c444f                          0.0s
 => => extracting sha256:e1c681003a03fff277ecf90fccf526881bcc2e006c9e371b58f45680d54c1954                          0.0s
 => => extracting sha256:a85ccd8c07bd7090e8a37ab878413b035a370e872367b145a0c0aaaaf60ccbdf                          0.5s
 => [2/2] RUN echo 'Hello Nerdctl From Containerd' > /usr/share/nginx/html/index.html                              0.1s
 => exporting to docker image format                                                                               6.2s
 => => exporting layers                                                                                            5.6s
 => => exporting manifest sha256:dab994ac6deff60045929e5b3ba15165a538b6054bb382f9bd3d884a73b86e32                  0.0s
 => => exporting config sha256:e728497d739a1956f9ca87173fc1a5e89c2d0e392b9a04a453f6a21f79cd9497                    0.0s
 => => sending tarball                                                                                             0.6s
unpacking docker.io/library/nginx:nerctl (sha256:dab994ac6deff60045929e5b3ba15165a538b6054bb382f9bd3d884a73b86e32)...
Loaded image: docker.io/library/nginx:nerctl

[root@rocky9-2 ~]# nerdctl images
REPOSITORY                          TAG       IMAGE ID        CREATED           PLATFORM       SIZE        BLOB SIZE
nginx                               nerctl    dab994ac6def    48 seconds ago    linux/amd64    44.2 MiB    17.1 MiB
harbor.raymonds.cc/library/redis    alpine    c476327f7a62    5 minutes ago     linux/amd64    41.4 MiB    16.0 MiB

3)打标签 tag

[root@rocky9 ~]# nerdctl tag nginx:nerctl harbor.raymonds.cc/library/nginx:nerctl

[root@rocky9-2 ~]# nerdctl images
REPOSITORY                          TAG       IMAGE ID        CREATED           PLATFORM       SIZE        BLOB SIZE
nginx                               nerctl    dab994ac6def    48 seconds ago    linux/amd64    44.2 MiB    17.1 MiB
harbor.raymonds.cc/library/redis    alpine    c476327f7a62    5 minutes ago     linux/amd64    41.4 MiB    16.0 MiB

4)将镜像推送到 Harbor

开始将镜像推送到 harbor

[root@rocky9-2 ~]# nerdctl push harbor.raymonds.cc/library/nginx:nerctl

可以看到镜像已经上传到harbor镜像仓库

t1-6

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/499899.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SSM的高校普法系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的高校普法系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

每天五分钟深度学习:使用神经网络完成人脸的特征点检测

本文重点 我们上一节课程中学习了如何利用神经网络对图片中的对象进行定位,也就是通过输出四个参数值bx、by、bℎ和bw给出图片中对象的边界框。 本节课程我们学习特征点的检测,神经网络可以通过输出图片中对象的特征点的(x,y)坐标来实现对目标特征的识别,我们看几个例子。…

Oracle-MNIST代码学习

一、网络结构 二、代码学习 2.1、x = F.relu(self.conv1(x)) # self.conv1 = nn.Conv2d(1, 20, 5, 1) ​​​​​ 1)Conv2d 详解参考:PyTorch nn.Conv2d - 知乎 2) relu pytorch学习线性回归与非线性回归,以及理解nn.linear()和ReLU激活函数_pytorch 非线性函数作用-C…

访学博后须知|携带手机等电子产品入境美国注意事项

美国对携带手机等电子产品入境有着严格的规定&#xff0c;因此知识人网小编提醒拟出国做访问学者、博士后或联合培养的博士生了解以下注意事项&#xff0c;尽量减少不必要的麻烦。 随着互联网的普及&#xff0c;手机等电子产品在人民生活中占有不可或缺的地位。因为研究和工作需…

AcWing刷题-空调

空调 差分&#xff1a; N int(input()) p list(map(int, input().split())) t list(map(int, input().split())) d,s[0]*100010,[0]*100010 for i in range(N):d[i] p[i]-t[i]for i in range(N):s[i] d[i]s[i1] - d[i] ans 0 for i in range(N1):if s[i]>0:ans s[i]…

大话设计模式之代理模式

代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许通过代理对象控制对另一个对象的访问。代理对象充当客户端和实际对象之间的中介&#xff0c;客户端通过代理对象间接访问实际对象&#xff0c;从而可以在访问控制、缓存、延迟加载等方面提…

二维随机变量的条件分布-已知X概率密度,X条件下的Y概率密度求解y的概率密度

问题&#xff1a;设数X在区间(0,1)上随机地取值,当观察到Xx(0<x<1)时,数Y在区间(x,1)上随机地取值.求Y的概率密度f(y)&#xff1f; 求解&#xff1a; 首先&#xff0c;数X在区间(0,1)上均匀分布&#xff0c;因此其概率密度函数fX​(x)为&#xff1a; fX​(x)1 0<…

PLC_博图系列☞N:扫描操作数的信号下降沿

PLC_博图系列☞N&#xff1a;扫描操作数的信号下降沿 文章目录 PLC_博图系列☞N&#xff1a;扫描操作数的信号下降沿背景介绍N&#xff1a;扫描操作数的信号下降沿说明参数示例 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 N 背景介绍 这是一篇关于PLC编程的文章…

代码随想录算法训练营第二十四天| 理论基础,77. 组合

题目与题解 参考资料&#xff1a;回溯法理论基础 带你学透回溯算法&#xff08;理论篇&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 77. 组合 题目链接&#xff1a;​​​​​​​​​​​​​​77. 组合 代码随想录题解&#xff1a;77. 组合 视频讲解&#xff…

AI的“换脸“魔术,究竟是弊大于利还是利大于弊?

公众号&#xff1a;【可乐前端】&#xff0c;每天3分钟学习一个优秀的开源项目&#xff0c;分享web面试与实战知识&#xff0c;也有全栈交流学习摸鱼群&#xff0c;期待您的关注! 每天3分钟开源 hi&#xff0c;这里是每天3分钟开源&#xff0c;很高兴又跟大家见面了&#xff0…

知识图谱与大数据:区别、联系与应用

目录 前言1 知识图谱1.1 定义1.2 特点1.3 应用 2 大数据2.1 定义2.2 应用 3. 区别与联系3.1 区别3.2 联系 结语 前言 在当今信息爆炸的时代&#xff0c;数据成为了我们生活和工作中不可或缺的资源。知识图谱和大数据是两个关键概念&#xff0c;它们在人工智能、数据科学和信息…

C++入门知识(1)

命名空间的引入 C语言的缺陷以及C的解决。 看下面这个代码&#xff1a; 这里进行了报错。 这里包含rand所在的头文件&#xff0c;然后头文件会进行展开。然后头文件里的rand和全局变量rand就会发生冲突。 这个就叫做命名冲突。 因此C引入了一个解决办法 namespace&#x…

EasyRecovery2024 安装步骤及功能特色介绍

在数字化时代&#xff0c;数据的重要性不言而喻。无论是个人用户还是企业用户&#xff0c;都可能面临数据丢失的风险。为了应对这一挑战&#xff0c;EasyRecovery作为一款专业的数据恢复软件&#xff0c;成为了越来越多人的选择。 EasyRecovery以其强大的功能和易用的界面&…

老阳推荐的视频号项目是真的吗?能赚钱吗?

在当下数字化、信息化的社会背景下&#xff0c;视频号项目如雨后春笋般涌现&#xff0c;成为许多人关注的焦点。特别是在一些知名人士&#xff0c;如老阳的推荐下&#xff0c;这些项目更是受到了广泛的关注和讨论。那么&#xff0c;老阳推荐的视频号项目是否真实存在?它能否真…

一篇复现Dockerfile指令

华子目录 制作镜像基于dockerfile制作镜像dockerfile介绍注意 格式PATH上下文路径URL- Dockerfile指令-FROM指令格式示例 Dockerfile指令-MAINTAINER指令介绍示例 Dockerfile指令-COPY指令介绍示例1示例2 Dockerfile指令-ADD指令介绍示例 Dockerfile指令-WORKDIR指令介绍示例 D…

【详细讲解Android Debug Bridge各种命令及用法的文章】

&#x1f525;博主&#xff1a;程序员不想YY啊&#x1f525; &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f4ab; &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 &#x1f308;希望本文对您有所裨益&#xff0c;如有…

蓝桥杯23年第十四届省赛真题-填充|DFS,贪心

题目链接&#xff1a; 1.填充 - 蓝桥云课 (lanqiao.cn) 蓝桥杯2023年第十四届省赛真题-填充 - C语言网 (dotcpp.com) 说明&#xff1a; dfs就不再多说了&#xff0c;对于每个?都有0和1两个分支&#xff0c;数据范围是&#xff1a; 那么有m个 ?&#xff0c;时间复杂度就是…

某物登录表单加密

之前分析过某物h5的以及小程序的搜索接口,就是一个aes,秘钥不固定,表单里把秘钥以及密文一起发过去,服务器解密后再把数据加密返回,客户端解密展示到页面上. 这期是关于app的登录,密码登录 声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;…

人工智能:数字化转型中的关键角色

人工智能&#xff1a;数字化转型中的关键角色 数字化转型是十多年来商业变革的核心&#xff0c;它本身也在人工智能的崛起中发生转变。人工智能有望极大地改变数字化转型&#xff0c;从企业设定的目标到从业者用来推进计划的工具。本文将深入探讨人工智能在数字化转型中的扮演的…

Rust编程(四)PackageCrateModule

这一部分的中文教程/文档都很混乱,翻译也五花八门,所以我建议直接看英文官方文档,对于一些名词不要进行翻译,翻译只会让事情更混乱,本篇从实战和实际需求出发,讲解几个名称的关系。 Module & Crate & Package & Workspace 英文中的意思: Cargo:货物 Crate:…