Please enable Javascript to view the contents

如何在 Kubernetes 集群集成 Kata

 ·  ☕ 4 分钟

1. Kata 解决什么问题

安全性和隔离性是 Kata Container 显著区别于 Docker Container 的地方。

Kata Container 来源于 Intel Clear Containers 和 Hyper runV 项目的合并。Intel Clear Containers 借助 Intel VT-x 技术使用轻量级虚拟机提供容器,解决安全性问题,同时性能优异。而 Hyper runV 对标的是 Docker 的 runc ,提供容器的运行时,遵循 OCI runtime 规范。

2. Kubernetes 中的 Kata

2.1 OCI 和 CRI-O

OCI 标准是为了避免容器标准被 Docker 独家挟持而出现的。

CRI 标准将 Kubelet 与运行时解耦,实现 CRI 标准的容器管理程序都可以用于 Pod 创建。

CRI-O 插件同时实现了 CRI 和 OCI 标准,可以用于替换 Containerd 直接与 runc 等 OCI runtime 对接。

如下图:

2.2 Kata 与 Containerd

为了兼容 OCI 标准,Docker 将管理运行时的功能从 Docker Daemon 中剥离出来,形成了 Containerd 。在运行容器时,可以不用 Docker 的 runc ,而替换为 kata-runtime 。

2.3 Kata 与 Kuberntes 的集成

如下图,Kata 主要替换的是 OCI runtime 层,其他部分与基于 Docker runc 的 Kubernetes 并无差异。同时,基于 kata-runtime 的 Pod 和基于 runc 的 Pod 可以共存于集群之中。

目前的主要问题是,Kata 不支持 host 网络。而 Kubernetes 中,etcd、nodelocaldns、kube-apiserver、kube-scheduler、metrics-server、node-exporter、kube-proxy、calico、kube-controller-manager 等,也就是 Static Pod 和 Daemonset 都会使用 host 网络。所以在安装部署时,依然使用 runc 作为默认的运行时,而将 kata-runtime 作为可选的运行时给特定的负载使用。

3. Kubernetes 集群集成 Kata

3.1 安装 Kubernetes 集群

使用 Kubeadm 安装集群非常方便,可以参考之前的文档 使用 Kubeadm 安装 Kubernetes 集群

也可以直接参考官方文档,https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/ 。

由于,Kata 需要硬件虚拟化支持,IaaS 厂商一般没有开启相关的功能。我使用的是物理机,只能使用国内的网络。下面的脚本,可以用来提前下载相关镜像。

  • 查询镜像列表
1
2
3
4
5
6
7
8
9
kubeadm config images list

k8s.gcr.io/kube-apiserver:v1.17.9
k8s.gcr.io/kube-controller-manager:v1.17.9
k8s.gcr.io/kube-scheduler:v1.17.9
k8s.gcr.io/kube-proxy:v1.17.9
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:v3.3.12
k8s.gcr.io/coredns:1.6.9
  • 下载镜像
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
images=(
  kube-apiserver:v1.17.9
  kube-controller-manager:v1.17.9
  kube-scheduler:v1.17.9
  kube-proxy:v1.17.9
  pause:3.1
  etcd:v3.3.12
  coredns:1.6.9
)

for imageName in ${images[@]} ; do
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageName
    docker rmi registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName
done
  • 查看安装的 Kubernetes 版本
1
2
3
4
kubectl version

Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:18:16Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:10:45Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}

3.2 安装 Kata 命令行工具

以 CentOS 操作系统为例:

1
2
3
4
5
6
source /etc/os-release
yum -y install yum-utils
ARCH=$(arch)
BRANCH="${BRANCH:-master}"
yum-config-manager --add-repo "http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/CentOS_${VERSION_ID}/home:katacontainers:releases:${ARCH}:${BRANCH}.repo"
yum -y install kata-runtime kata-proxy kata-shim

3.3 检测硬件是否支持 Kata

Kata 对硬件的要求需要满足以下任意条件:

  • Intel VT-x technology.
  • ARM Hyp mode (virtualization extension).
  • IBM Power Systems.
  • IBM Z mainframes.

安装完 kata-runtime 之后,执行检测命令:

1
2
3
4
kata-runtime kata-check

System is capable of running Kata Containers
System can currently create Kata Containers

这里的输出表示,运行环境支持 Kata Containers 。

3.4 配置并测试 Docker

  • 配置 kata-runtime 参数
1
vim /etc/docker/daemon.json

新增如下内容,默认依然使用 runc,但是通过指定 runtime 参数可以使用 Kata 。

1
2
3
4
5
6
7
{
  "runtimes": {
    "kata-runtime": {
      "path": "/usr/bin/kata-runtime"
    }
  }
}
  • 重启 Docker 服务
1
2
systemctl daemon-reload
systemctl restart docker
  • 测试 Kata 是否安装成功
1
2
3
docker run --runtime=kata-runtime  busybox uname -a

Linux 249a23f53475 5.4.60-65.1.container #1 SMP Thu Jan 1 00:00:00 UTC 1970 x86_64 GNU/Linux
1
2
3
docker run busybox uname -a

Linux b4812ed8990c 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 GNU/Linux

kata-runtime 容器使用的内核版本与宿主机不同,这就说明 kata-runtime 配置成功了。

3.5 配置 Kubelet

  • 新增配置文件
1
2
3
4
5
mkdir -p  /etc/systemd/system/kubelet.service.d/
cat << EOF | sudo tee  /etc/systemd/system/kubelet.service.d/0-containerd.conf
[Service]                                                 
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
  • 重启生效
1
2
systemctl daemon-reload
systemctl restart kubelet

这里使用的是 containerd 。如果使用 CRI-O ,配置会不一样。

3.6 给 Kubernetes 提供 kata-runtime

通过直接创建 Container 可以使用 kata-runtime 。但在集群中,我们该如何告诉 Kubernetes 哪些负载需要使用 kata-runtime 呢?根据不同的版本,Kata 提供了不同的方式。

首先都需要生成 containerd 配置文件

1
containerd config default > /etc/containerd/config.toml
  • RuntimeClass 的方式

这种方式对相关组件版本有要求:

Kata Containers v1.5.0 or above (including 1.5.0-rc)
Containerd v1.2.0 or above
Kubernetes v1.12.0 or above

在 config.toml 配置文件中,增加如下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    [plugins.cri.containerd]
      no_pivot = false
    [plugins.cri.containerd.runtimes]
      [plugins.cri.containerd.runtimes.runc]
         runtime_type = "io.containerd.runc.v1"
         [plugins.cri.containerd.runtimes.runc.options]
           NoPivotRoot = false
           NoNewKeyring = false
           ShimCgroup = ""
           IoUid = 0
           IoGid = 0
           BinaryName = "runc"
           Root = ""
           CriuPath = ""
           SystemdCgroup = false
      [plugins.cri.containerd.runtimes.kata]
         runtime_type = "io.containerd.kata.v2"
      [plugins.cri.containerd.runtimes.katacli]
         runtime_type = "io.containerd.runc.v1"
         [plugins.cri.containerd.runtimes.katacli.options]
           NoPivotRoot = false
           NoNewKeyring = false
           ShimCgroup = ""
           IoUid = 0
           IoGid = 0
           BinaryName = "/usr/bin/kata-runtime"
           Root = ""
           CriuPath = ""
           SystemdCgroup = false

这里 [plugins.cri.containerd.runtimes.kata] 中的 kata 将被作为 RuntimeClass handler 关键字。

  • 使用 untrusted_workload_runtime 的方式

对于不符合上述版本要求的环境,可以使用之前的方式。

在配置文件中新增如下内容:

1
2
3
    [plugins.cri.containerd.untrusted_workload_runtime]
      runtime_type = "io.containerd.runtime.v1.linux"
      runtime_engine = "/usr/bin/kata-runtime"

最后,都需要重启 containerd。

1
2
containerd systemctl daemon-reload
systemctl restart containerd

4. 使用 kata-runtime

4.1 RuntimeClass 方式

  • 创建 RuntimeClass

kata-runtime.yaml

1
2
3
4
5
kind: RuntimeClass
apiVersion: node.k8s.io/v1beta1
metadata:
  name: kata-containers
handler: kata

也可以为 runc 创建 RuntimeClass

1
2
3
4
kubectl get runtimeclass

NAME              CREATED AT
kata-containers   2020-08-30
  • 创建负载 kata-pod.yaml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Pod
metadata:
  name: kata-nginx
spec:
  runtimeClassName: kata-containers
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
1
kubectl apply -f kata-pod.yaml
  • 查看负载
1
kata-runtime list

4.2 untrusted_workload_runtime 的方式

untrusted_workload_runtime 使用 annotations 告诉 Kubernetes 集群哪些负载需要使用 kata-runtime。

1
2
annotations:
  io.kubernetes.cri.untrusted-workload: "true"

下面是一个示例 kata-pod-untrusted.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: Pod
metadata:
  name: kata-nginx-untrusted
  annotations:
    io.kubernetes.cri.untrusted-workload: "true"
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
1
kubectl apply -f kata-pod-untrusted.yaml

5. 参考


微信公众号
作者
微信公众号