k8s 容器引擎介绍

1. docker与containerd对比

在 V1.24 版本以前 k8s 默认使用docker容器引擎

在 V1.24 版本以后 k8s 移除了dockershim,改为默认使用Containerd

1.1. 调用链路的区别

使用docker作为容器引擎时需要通过dockershim对接docker再调用containerd。

使用containerd作为容器引擎时kubelt可以通过CRI-containerd直接调用containerd。

1.2. 标准输出日志路径的区别

dockercontainerd
储存路径如果 Kubernetes 使用 Docker 作为容器运行时,容器日志的落盘由docker来完成, 日志通常存储在 /var/lib/docker/containers/<container-id>-json.log。如果 Kubernetes 使用 containerd 作为容器运行时,容器日志的落盘由kubelet来完成,路径 为/var/log/pods/<namespace>_<pod-name>_<pod-uid>/<container-name>/<container-id>,同时在/var/log/containers目录下创建软链接,指向日志文件
配置参数在docker配置文件中指定:
“log-driver”: “json-file”,
“log-opts”: {“max-size”: “100m”,”max-file”: “5”}
方法一:在kubelet参数中指定: –container-log-max-files=5 –container-log-max-s

1.3. 配置文件路径

containerd配置文件/etc/containerd/config.toml


# 默认配置中还有两个关于存储的配置路径:
# 1、保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据
root = "/var/lib/containerd"  
# 2、保存运行时的临时数据的,包括 sockets、pid、挂载点、运行时状态以及不需要持久化的插件数据。
state = "/run/containerd"   
ShellScript

2. containerd 客户端命令介绍

2.1. crictl、ctr 命令

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

  • crictl 命令(k8s提供):crictl 是遵循 CRI 接口规范的一个命令行工具,通常用它来检查和管理kubelet节点上的容器运行和镜像。
  • ctr 命令(containerd提供):ctr 是 containerd 的一个客户端工具。
  • 二者区别:ctr -v 输出的是 containerd 的版本,crictl -v 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。

注意:

# 使用crictl命令之前,需要先配置/etc/crictl.yaml如下(不配置的话,你用该命令会一直报warn警告)
cat > /etc/crictl.yaml << 'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF

# 也可以通过命令进行设置(会自动生成/etc/crictl.yaml)
sudo crictl config runtime-endpoint unix:///run/containerd/containerd.sock
sudo crictl config image-endpoint unix:///run/containerd/containerd.sock
ShellScript

基础操作命令:

# 用于列出当前系统中的命名空间(namespaces)
sudo ctr ns ls
NAME    LABELS        
k8s.io
         
# 用于列出指定命名空间(namespace)中的镜像(images)列表
sudo ctr -n k8s.io image ls


# crictl 没有-n参数,操作都默认在`k8s.io`命名空间下
sudo crictl images 
sudo crictl pods
ShellScript

2.2. nerdctl 命令

前面我们介绍了可以使用 ctr 操作管理 containerd 镜像容器,但是大家都习惯了使用 docker cli,ctr 使用起来可能还是不太顺手,为了能够让大家更好的转到 containerd 上面来,社区提供了一个新的命令行工具:nerdctl。

nerdctl 是一个与 docker cli 风格兼容的 containerd 客户端工具,而且直接兼容 docker compose 的语法,这就大大提高了直接将 containerd 作为本地开发、测试或者单机容器部署使用的效率。

安装:

# 如果没有安装 nerdctl,则可以下载 nerdctl-full-<VERSION>-linux-amd64.tar.gz 包进行安装
wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz

mkdir -p /usr/local/containerd/bin/ && tar -zxvf nerdctl-1.7.6-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/bin/

ln -s /usr/local/containerd/bin/nerdctl /usr/local/bin/nerdctl
 [root@k8s-node-01 ~]# nerdctl version # 报错warn,提示buildkit未安装
WARN[0000] unable to determine buildctl version: exec: "buildctl": executable file not found in $PATH 
Client:
 Version:   v1.7.6
安装buildkit(参考:https://zhuanlan.zhihu.com/p/366671300)
wget https://github.com/moby/buildkit/releases/download/v0.13.2/buildkit-v0.13.2.linux-amd64.tar.gz
解压后得到一个bin目录,把这个bin目录放到 $PATH 里去
ShellScript

2.3. 客户端命令 docker、ctr、crictl、nerdctl 详解

2.3.1. 名称空间

可以用 -n 指定名称空间,可以将镜像或者容器分散到不同的空间内,但并非所有命令都支持

dockerctr (containerd)crictl(k8s)nerdctl
是否支持不支持支持不支持支持
示例ctr ns ls

ctr -n k8s.io image ls # 查看指定名称空间下的镜像

ctr -n k8s.io container ls # 查看指定名称空间下的容器

默认所有操作都在k8s.io名称空间下
nerdctl -n k8s.io image ls

nerdctl -n k8s.io
container ls

2.3.2. 镜像相关命令

命令dockerctrcrictlnerdctl
查看本地镜像docker imagesctr image lscrictl images同docker命令
下载/拉取镜像docker pullctr image pullctictl pull同docker命令
给镜像打标签docker tagctr image tag同docker命令
上传/推送镜像docker pushctr image push同docker命令
删除本地镜像docker rmictr image rmcrictl rmi同docker命令
查看镜像详情docker inspectcrictl inspecti # 注意末尾是小写字母
i
同docker命令
导出镜像docker savectr image export同docker命令
导入镜像docker loadctr image import xx.tar docker.io/library/nginx:alpine同docker命令
登录镜像仓库docker login不支持,理由:ctr 工具主要是用于底层的容器操作和管
理,而不是直接与镜像仓库进行交互如推拉镜像等。
不支持,理由:主要用于管理 Pod
和容器,而非直接与镜像仓库交互。
支持
ctr(containerd)镜像命令详解
# 1、查看全部镜像
sudo ctr image ls      # 分字段展示
sudo ctr image ls -q   # 列出本地存储中的镜像(images)的 ID 列表,而不显示详细的镜像信息。
sudo ctr image check   # 检测default名称空间下所有镜像的可用性,主要看STATUS为complete代表可用

# 2、拉取 Docker Hub 官方镜像 nginx:alpine,需要注意的是镜像地址需要加上 docker.io Host 地址
sudo ctr images pull docker.io/library/nginx:alpine 

# 3、重新打标签
sudo ctr image tag docker.io/library/nginx:alpine harbor.k8s.local/course/nginx:alpine

# 4、上传镜像
sudo ctr images push docker.io/library/nginx:alpine --user xxx 

# 5、删除镜像
sudo ctr image rm harbor.k8s.local/course/nginx:alpine

# 6、查看镜像详情


# 7、将镜像导出为压缩包
sudo ctr image export nginx.tar.gz docker.io/library/nginx:alpine
sudo ctr -n k8s.io image export  a.tar.gz registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.11.1

# 8、从压缩包导入镜像
sudo ctr image import nginx.tar.gz
sudo ctr -n default image import a.tar.gz
# 直接导入可能会出现类似于 ctr: content digest sha256:xxxxxx not found 的错误,要解决这个办法需要 pull 可以通用/适用所有平台的镜像:
sudo ctr i pull --all-platforms docker.io/library/nginx:alpine
sudo ctr i export --all-platforms nginx.tar.gz docker.io/library/nginx:alpine
sudo ctr i rm docker.io/library/nginx:alpine
sudo ctr i import nginx.tar.gz

# 9、将镜像挂载到主机目录
sudo ctr image mount docker.io/library/nginx:alpine /mnt
sudo ctr image unmount /mnt

# 10、命名空间:Containerd 也有 namespaces 的概念,镜像或容器可以分散到不同的空间,对于多租户的场景十分有用
sudo ctr ns ls 
sudo ctr ns create test
sudo ctr ns rm test
sudo ctr -n test image ls
# 说明:
# 1、Docker 其实也是默认调用的 containerd,事实上 Docker 使用的 containerd 下面的命名空间默认是 moby,而不是 default
# 2、Kubernetes 下使用的 containerd 默认命名空间是 k8s.io
ShellScript
crictl(kubernetes)镜像命令详解
# crictl 没有-n参数,操作都在`k8s.io`命名空间下。
# sudo crictl image list 等同于 sudo ctr -n=k8s.io image list
# sudo crictl image ls   等同于 sudo ctr -n=k8s.io image ls

# 注意:
# sudo ctr images pull 拉取的镜像默认放在 default 而 sudo crictl pull 和 kubelet 默认拉取的镜像都在 k8s.io 命名空间下。所以通过 ctr 导入镜像的时候特别注意一点,最好指定命名空间。
ShellScript
nerdctl镜像命令详解
# 镜像管理
nerdctl images
nerdctl pull docker.io/library/busybox:latest
nerdctl login --username=xxx --password yyy registry.cn-shanghai.aliyuncs.com
nerdctl tag centos:7 registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl push registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl save -o busybox.tar.gz busybox:latest
nerdctl load -i busybox.tar.gz
nerdctl rmi busybox
 
# ctr不能 build 镜像,我们可以用 nerdctl
# 1、Dockerfile文件如下
FROM centos:7
CMD sleep 1000

# 2、构建镜像
nerdctl build -t test:v1.0 -f Dockerfile 
# 可以看到有一个错误提示,需要我们安装 `buildctl` 并运行 `buildkitd`,这是因为 `nerdctl build` 需要依赖 `buildkit` 工具。
# buildkit 项目也是 Docker 公司开源的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:
# 1、服务端 `buildkitd`:当前支持 runc 和 containerd 作为 worker,默认是 runc,我们这里使用 containerd
# 2、客户端 `buildctl`:负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求
# buildkit 是典型的 C/S 架构,客户端和服务端是可以不在一台服务器上,而 `nerdctl` 在构建镜像的时候也作为 `buildkitd` 的客户端,所以需要我们安装并运行 `buildkitd`。

# 安装buildkit
wget https://github.com/moby/buildkit/releases/download/v0.13.2/buildkit-v0.13.2.linux-amd64.tar.gz

tar -zxvf buildkit-v0.13.2.linux-amd64.tar.gz -C /usr/local/containerd/
ln -s /usr/local/containerd/bin/buildkitd /usr/local/bin/buildkitd
ln -s /usr/local/containerd/bin/buildctl /usr/local/bin/buildctl

cat > /etc/systemd/system/buildkit.service << "EOF"
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
[Service]
ExecStart=/usr/local/bin/buildkitd --oci-worker=false --containerd-worker=true
[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable buildkit --now
systemctl status buildkit.service

# 重新构建镜像
[root@k8s-node-01 test]# nerdctl build -t test:v1.0 -f Dockerfile
FATA[0000] lstat /test/Containerfile: no such file or directory 
[root@k8s-node-01 test]# ls
dockerfile
[root@k8s-node-01 test]# 
[root@k8s-node-01 test]# mv dockerfile Containerfile
[root@k8s-node-01 test]# nerdctl build -t test:v1.0 -f Dockerfile
[root@k8s-node-01 test]# nerdctl images 

# 启动测试
nerdctl run -d --name=test test:v1.0
nerdctl container ls
nerdctl exec -ti test sh
ShellScript

2.3.2. 容器相关命令

命令dockerctrcrictl
显示本地运行的容器docker ps ctr task ls/ctr container lscrictl ps
创建一个新容器docker createctr container createcrictl create
运行一个新容器docker runctr run无(最小单元为 pod)
启动容器docker startctr task startcrictl start
关闭容器docker stop ctr task killcrictl stop
删除容器docker rmctr container rmcrictl rm
查看容器详情docker inspectctr container infocrictl inspect
查看容器日志docker logscrictl logs
查看容器资源docker statscrictl stats
进入容器内部docker execcrictl exec
清空不用的容器docker image prunecrictl rmi –prune
ctr(containerd)镜像命令详解
# 容器操作
## 创建容器
ctr image pull docker.io/library/nginx:alpine --hosts-dir=/etc/containerd/certs.d
ctr container create docker.io/library/nginx:alpine nginx

## 查看容器
ctr container ls
ctr container ls -q
ctr container info nginx
## 删除容器
ctr container rm nginx


# 任务
## (1)任务介绍
# 上面用container create只是创建了一个静态的容器对象,把运行容器需要的资源及配置数据例如namespaces、rootfs和容器的配置都初始化完毕了,但是容器内的进程还没有启动,即容器尚未处于运行状态

## (2) 启动任务(激活容器)
ctr task start -d nginx # nginx是你创建的容器名字

## (3)查看
ctr task ls

## (4)进入容器
# 注意必须要指定 --exec-id 参数,这个 id 可以随便写,只要唯一就行。
ctr task exec --exec-id 0 -t nginx sh

## (5)暂停容器
ctr task pause nginx  # 可以查看容器ctr task ls发现状态变成PAUSED

## (6)恢复容器
ctr task resume nginx 

## (7)ctr无法stop容器,只能暂停或杀死
ctr task kill nginx  # 可以查看容器ctr task ls发现状态变成STOPPED

## (8)删掉
ctr task rm nginx

## (9)获取容器cgroup相关信息(内存、CPU 和 PID 的限额与使用量。)
ctr task metrics nginx # 记得要先启动才能看:ctr task start -d nginx

## (10)看容器中所有进程在宿主机中的 PID
ctr task ps nginx  # 第一行的就对应容器内的1号进程
ShellScript
nerdctl 镜像命令详解
# 容器管理
nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine
nerdctl exec -it nginx /bin/sh
nerdctl ps 
nerdctl ps -a
nerdctl inspect nginx
nerdctl logs
nerdctl logs -f
nerdctl stop nginx
nerdctl rm nginx
nerdctl rm -f nginx


# 更多命令操作,可以直jgdddgjkdgbkhgh接在命令行输入命令查看帮助。
docker --help
ctr --help
crictl --help
ShellScript

3. kubectl 命令介绍

3.1. 基本语法

kubectl [command] [TYPE] [NAME] [flags]

# command
## 子命令,用于操作资源对象,例如create、get、describe、delete等

# TYPE
## 资源类型,区分大小写,并且可以简写,例如下述三个命令效果相同
kubectl get pods xxx
kubectl get pod xxx
kubectl get po xxx

# NAME
## 具体的资源名,区分大小写,如果不指定具体的资源NAME,则默认返回全部,并且在一条命令里指定多个资源操作
kubectl get pod xxx yyy zzz
kubectl get pod/xxx deployment/aaa
kubectl apply -f 1.yaml -f 2.yaml
# 了解:
kubectl create -f 1.yaml # 只能用于创建新资源,如果资源已存在create -f会报错
kubectl apply -f 1.yaml # 创建或更新,所以推荐使用apply -f

# flags
## 可选参数,例如
kubectl get pods xxx -o wide
kubectl get pods xxx -o yaml
ShellScript

2.2. 常用用法

2.2.1. 查看

# 查看帮助文档
kubectl --help
kubectl apply --help # 查看二级帮助文档
kubectl api-resources # 查看资源类型

# 示例
kubectl get deploy,pods -o wide -n 某个名称空间 # -n可以直接跟在kubectl后 
kubectl get deploy,pods -o wide -A # -A不能直接跟在kubectl后,要往后放,代表查看所有名称空间,
kubectl get deploy 具体的deploy名 -o yaml 
kubectl logs -f pod名
kubectl describe node node01

# 关于describe的结果示例:
# Controlled By 指明此 Pod 是由 ReplicaSet/xxx 创建。Events 记录了 Pod 的启动过程。如果操作失败(比如 image 不存在),也能在这里查看到原因
ShellScript

2.2.2. 增加

# 基于yaml创建
kubectl apply -f 1.yaml

# 直接用命令创建,
# 例如:启动临时容器,用于测试,exit退出后则删除
kubectl run -i --tty --image busybox:1.27 egon-test --restart=Never --rm sh
ShellScript

2.2.3. 改

# 修改副本
kubectl scale deployment xxx --replicas=0

# 在线编辑
kubectl edit deployment xxx
ShellScript

2.2.4. 删

kubectl delete deloyment xxx

kubectl delete pods,services -l <label-key>=<label-value>  # 删除带有标签<label-key>=<label-value>的pod和svc
# 查出标签:kubectl  get pods --show-labels

kubectl delete -f 1.yaml
ShellScript

2.2.5. 进入pod内部

kubectl exec -it pod名字 -- bash

# 拷贝文件 
kubectl cp pod名:/etc/fstab /tmp/a.txt # pod内文件拷贝到本机,必须指定文件名
kubectl cp /tmp/a.txt pod名:/tmp  # 本机拷贝到pod内
ShellScript