关于kubernetes:Container-Runtimes四-Kubernetes-Container-Runtimes-CRI

28次阅读

共计 3760 个字符,预计需要花费 10 分钟才能阅读完成。

引言

这是对于容器运行时系列文章的第四篇,也是最初一篇。从第 1 篇开始曾经有一段时间了,在那篇文章中,我概述了容器运行时,并探讨了低级和高级运行时之间的区别。在第 2 篇文章中,我具体介绍了低级容器运行时,并构建了一个简略的低级运行时。在第 3 篇文章中,我降级了技术栈,介绍了高级容器运行时。

Kubernetes 运行时反对容器运行时接口(CRI)的高级容器运行时。CRI 在 Kubernetes 1.5 中引入,并充当 kubelet 和容器运行时之间的桥梁,冀望与 Kubernetes 集成的高级容器运行时实现 CRI。预计运行时将解决镜像治理并反对 Kubernetes Pod,并治理各个容器,因而依据咱们在第 3 篇文章中的定义,Kubernetes 运行时必须是高级运行时。低级运行时短少一些必要的个性。因为第 3 篇文章介绍了无关高级容器运行时的所有内容,因而在本文中,我将重点介绍 CRI,并介绍一些反对 CRI 的运行时。

为了更多地理解 CRI,值得看一下 Kubernetes 架构。Kubelet 是一个位于 Kubernetes 集群中每个工作节点上的代理。Kubelet 负责管理其节点的容器工作负载,当波及到理论运行工作负载时,kubelet 应用 CRI 与在同一节点上运行的容器运行时进行通信。这样,CRI 仅仅是一个形象层或 API,它使您能够将容器运行时的实现独自拆分进去,而不用将其内置到 kubelet 中。

CRI 运行时示例

这里列出一些可与 Kubernetes 一起应用的 CRI 运行时。

containerd

containerd 是我在第 3 篇文章中提到的高级运行时。containerd 可能是以后最风行的 CRI 运行时,它将 CRI 实现作为默认状况下启用的插件。默认状况下,它在 unix socket 上开启监听,因而通过如下配置连贯到容器:

cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
EOF

这是一个乏味的高级运行时,因为它在 1.2 版开始通过称为“runtime handler”的货色反对多个低级运行时。runtime handler是通过 CRI 中的一个字段传递的,基于该运行时处理程序的容器将运行一个名为 shim 的应用程序以启动容器。它能够用于应用除 runc 之外的低级运行时来运行容器,例如 gVisorKata ContainersNabla Containersruntime handler在 k8s 1.12 alpha 版本的 RuntimeClass object 中正式被提交,这里有更多对于 containerd's shim 的概念介绍。

Docker

Docker runtime第一个实现了对 CRI 的反对,并且作为 kubeletDocker之间的一个 shim 而实现。从那以后,Docker已将其许多性能合成为容器,当初通过容器反对 CRI。装置最新版本的Docker 时,将同时装置 containerdCRI间接与 containerd 通信。因而,Docker自身并不需要反对 CRI。因而,依据你的理论状况,能够间接装置容器或者通过Docker 来装置。

cri-o

cri-o是一个轻量级的 CRI 运行时,它是 Kubernetes 特定的高级运行时。它反对 OCI 兼容镜像的治理,并从任何 OCI 兼容镜像注册表中提取。它反对 runcClear Containers作为低级运行时,在实践上反对其余 OCI 兼容的低级运行时,但依赖于与 runc OCI 命令行界面的兼容性,因而在实践中它不如容器的 shim API 灵便。
cri-oendpoints 默认状况下位于/var/run/crio/crio.sock,因而能够通过如下形式配置crictl:

cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///var/run/crio/crio.sock
EOF

CRI 标准

CRI是一个 protocol buffersgRPC API。该标准是在 kubelet 下的 Kubernetes 镜像仓库中的 protobuf 文件中定义的。CRI定义了几种近程过程调用(RPCs)和音讯类型。RPCs用于“镜像”(ImageService.PullImage),“创立容器”(RuntimeService.RunPodSandbox),“创立容器”(RuntimeService.CreateContainer),“启动容器”(RuntimeService.StartContainer),“进行容器”等操作(RuntimeService.StopContainer)等

例如,通过 CRI 启动一个新的 Kubernetes Pod 的典型交互看起来相似于以下内容(以我本人的伪 gRPC 模式,每个 RPC 都会失去一个更大的申请对象,为简便起见,我对其进行了简化)。RunPodSandboxCreateContainer RPC 在其响应中返回 ID,这些 ID 在后续申请中应用:

ImageService.PullImage({image: "image1"})
ImageService.PullImage({image: "image2"})
podID = RuntimeService.RunPodSandbox({name: "mypod"})
id1 = RuntimeService.CreateContainer({
    pod: podID,
    name: "container1",
    image: "image1",
})
id2 = RuntimeService.CreateContainer({
    pod: podID,
    name: "container2",
    image: "image2",
})
RuntimeService.StartContainer({id: id1})
RuntimeService.StartContainer({id: id2})

应用 crictl 工具能够间接与 CRI 运行时进行交互,能够间接从命令即将 gRPC 消 息发送到 CRI 运行时并用它来调试和测试 CRI 实现,而无需启动 kubelet 或 Kubernetes 集群,能够从 GitHub 上 cri-tools 版本页面 下载 crictl 二进制文件 来获取相干文件。
能够通过在 /etc/crictl.yaml 下创立配置文件来配置 crictl。在这里,你应该将运行时的gRPC 端点指定为 Unix socket 文件(unix:///path/to/file)或 TCP 端点(tcp://<host>:<port>)。在本例中将应用containerd

cat <<EOF | sudo tee /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
EOF

或者能够在每次命令行执行时指定runtime endpoint

crictl --runtime-endpoint unix:///run/containerd/containerd.sock …

应用 crictl 运行一个单容器 pod,首先,通知运行时pull 所需的 nginx 镜像,因为没有本地存储的镜像就无奈启动容器。

sudo crictl pull nginx

接下来创立一个 Pod 的创立申请,能够应用 JSON 文件进行操作。

cat <<EOF | tee sandbox.json
{
    "metadata": {
        "name": "nginx-sandbox",
        "namespace": "default",
        "attempt": 1,
        "uid": "hdishd83djaidwnduwk28bcsb"
    },
    "linux": { },
    "log_directory": "/tmp"
}
EOF

而后创立 pod sandbox,将sandbox 的 ID 存储为SANDBOX_ID

SANDBOX_ID=$(sudo crictl runp --runtime runsc sandbox.json)

接下来,在 JSON 文件中创立容器的创立申请。

cat <<EOF | tee container.json
{
  "metadata": {"name": "nginx"},
  "image":{"image": "nginx"},
  "log_path":"nginx.0.log",
  "linux": {}}
EOF

而后,在后面创立的 Pod 中创立并启动容器。

{CONTAINER_ID=$(sudo crictl create ${SANDBOX_ID} container.json sandbox.json)
  sudo crictl start ${CONTAINER_ID}
}

查看正在运行的 pod 以及正在运行的容器:

sudo crictl inspectp ${SANDBOX_ID}
sudo crictl inspect ${CONTAINER_ID}

通过进行并删除容器进行清理:

{sudo crictl stop ${CONTAINER_ID}
  sudo crictl rm ${CONTAINER_ID}
}

而后进行并删除Pod

{sudo crictl stopp ${SANDBOX_ID}
  sudo crictl rmp ${SANDBOX_ID}
}

正文完
 0