Deploy Kubernetes Cluster via Kubespray with Kata Container support on OTC

Kata Containers clearlinux.org
The following guide will help you to install a 2-node Kubernetes cluster with Kubespray and providing Kata Container support. The cluster will consist of one master server which will be built on ECS (Elastic Cloud Server) and one node which will be built on BMS (Bare Metal Server). BMS is being used due to a current limitation of ECS on OTC, the ECS does not support nested virtualization which would be required for Kata runtime.
===
High-Level Design
Section titled “High-Level Design”The following diagram shows the high-level Design:

Provision the underlying infrastructure on OTC
Section titled “Provision the underlying infrastructure on OTC”The underlying infrastructure consists of one ECS acting as Kubernetes master and one BMS acting as Kubernetes node. The table below shows some parameters of the servers used:
| ECS - Kubernetes Master | BMS - Kubernetes Node | |
|---|---|---|
| flavor | s2.large.2 | physical.p1.large |
| OS | Standard_CentOS_7_latest | Standard_CentOS_7_BMS_latest |
| Network | same VPC, Subnet, Security group* | same VPC, Subnet, Security group* |
| *The Security group being used is open any-any |
Disable the firewall on both the ECS and BMS instance
Section titled “Disable the firewall on both the ECS and BMS instance”In order to avoid any troubles with blocking firewall rules on either of the hosts disable the firewall on the OS with the following commands:
sudo systemctl stop firewalldsudo systemctl disable firewalldThe following steps need to be performed on the Kubernetes master from where Kubespray will install the cluster components
Section titled “The following steps need to be performed on the Kubernetes master from where Kubespray will install the cluster components”- Install Python 3 which will be required by Kubespray and Ansible
The standard CentOS image does not have EPEL repository by default which will be needed for the Python3 package. This can be installed with the following command:
rpm -ivf http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm- Install Python 3 and link Python 3.6 binary to Python 3
sudo yum -y install python36ln -s /usr/bin/python36 /usr/bin/python3- Clone the Kubespray repository and install the necessary requirements
git clone https://github.com/kubernetes-sigs/kubespray
#Install pipsudo yum install python-pip
#Requirements are incat requirements.txtansible>=2.5.0,!=2.7.0jinja2>=2.9.6netaddrpbr>=1.6hvac
#Install the requirementssudo pip install -r requirements.txt- Copy the private key for SSH key based authentication
Copy the SSH private key to the node that the linux user from the Kubernetes master from where Ansible will install everything is able to connect (don’t forget to have 600 permission on the key # chmod 600 ~/.ssh/id_rsa)
- Configure Kubespray - https://github.com/kubernetes-sigs/kubespray/blob/master/docs/getting-started.md
#copy the sample work directorycp -rfp inventory/sample inventory/mycluster
#192.168.1.75 is the IP of the kubernetes master - node1#192.168.1.116 is the IP of the kubernetes node - node2declare -a IPS=(192.168.1.175 192.168.1.116)
#create configCONFIG_FILE=inventory/mycluster/hosts.ini python3 contrib/inventory_builder/inventory.py ${IPS[@]}
#Modify the hosts.ini file as follows:cat inventory/mycluster/hosts.ini[all]node1 ansible_host=192.168.1.175 ip=192.168.1.175node2 ansible_host=192.168.1.116 ip=192.168.1.116
[kube-master]node1
[etcd]node1
[kube-node]node2
[k8s-cluster:children]kube-masterkube-node
[calico-rr]- Configure Kubespray to use CRI-O container runtime (currently Kata is supported by cri-o and cri-containerd only) - https://github.com/kubernetes-sigs/kubespray/blob/master/docs/cri-o.md
#Set the following variables in inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml
etcd_deployment_type: hostkubelet_deployment_type: hostcontainer_manager: crio
#Set the following variable in inventory/mycluster/group_vars/all/all.yml
download_container: false- Configure Kubespray to use FLANNEL CNI plugin
#Set the following variable in inventory/mycluster/group_vars/k8s-cluster/k8s-cluster.yml
kube_network_plugin: flannel- After we have successfully configured Kubespray we can start the deployment of Kubernetes cluster
ansible-playbook -i inventory/mycluster/hosts.ini cluster.yml -b -v --private-key=\~/.ssh/id_rsaAfter successful deployment now you should be able to switch to root user and check the Kubernetes cluster. Both node1 and node2 should be in STATUS Ready.
[linux@node1 ~]$ sudo su -Last login: Thu Dec 13 13:01:29 UTC 2018 on pts/0[root@node1 ~]# kubectl get node -o wideNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIMEnode1 Ready master 20h v1.13.0 192.168.1.175 <none> CentOS Linux 7 (Core) 3.10.0-862.14.4.el7.x86_64 cri-o://1.11.10node2 Ready node 20h v1.13.0 192.168.1.116 <none> CentOS Linux 7 (Core) 3.10.0-862.14.4.el7.x86_64 cri-o://1.11.10- Install the Kata and its components with kata-deploy - https://github.com/kata-containers/packaging/tree/master/kata-deploy
#Deploy the necessary RBAC objectskubectl apply -f https://raw.githubusercontent.com/kata-containers/packaging/master/kata-deploy/kata-rbac.yaml
#Deploy the Kata componentskubectl apply -f https://raw.githubusercontent.com/kata-containers/packaging/master/kata-deploy/kata-deploy.yamlThe above two commands will create daemonset Kubernetes object which will install the necessary Kata components on all supported nodes (currently Kata is supported on cri-o or cri-containerd), configures cri-o or cri-containerd to use Kata for untrusted workloads and last but not least will label the node with *kata-containers.io/kata-runtime=true * as you see below:
[root@node1 ~]# kubectl get node --show-labelsNAME STATUS ROLES AGE VERSION LABELSnode1 Ready master 21h v1.13.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=node1,node-role.kubernetes.io/master=node2 Ready node 21h v1.13.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kata-containers.io/container-runtime=cri-o,kata-containers.io/kata-runtime=true,kubernetes.io/hostname=node2,node-role.kubernetes.io/node=The following yaml file will create a kubernetes untrusted POD which will be spawned with kata runtime:
nginx-untrusted.yaml
apiVersion: v1kind: Podmetadata: annotations: io.kubernetes.cri-o.TrustedSandbox: "false" io.kubernetes.cri.untrusted-workload: "true" name: nginx-untrustedspec: containers: - name: nginx image: nginx nodeSelector: kata-containers.io/kata-runtime: "true"The following yaml file will create a kubernetes trusted POD which will be spawned with the default runc rutime:
nginx-trusted.yaml
apiVersion: v1kind: Podmetadata: name: nginx-trustedspec: containers: - name: nginx image: nginxIn the below example we can see that both PODs have been scheduled on node2, where nginx-trusetd POD has kernel from the underlying host and nginx-untrusted has its own kernel which is used by kata:
[root@node1 ~]# kubectl apply -f nginx-trusted.yamlpod/nginx-trusted created[root@node1 ~]# kubectl apply -f nginx-untrusted.yamlpod/nginx-untrusted created
[root@node1 ~]# kubectl get pod -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESnginx-trusted 1/1 Running 0 16s 10.233.65.9 node2 <none> <none>nginx-untrusted 1/1 Running 0 12s 10.233.65.10 node2 <none> <none>
[root@node1 ~]# kubectl exec -it nginx-trusted -- uname -r3.10.0-862.14.4.el7.x86_64
[root@node1 ~]# kubectl exec -it nginx-untrusted -- uname -r4.14.67