[ตอนที่ 3]Change Container-runtimes from Docker to CRI-O (update 20210122)
* Update ข้อมูลล่าสุดจาก https://www.blognone.com/node/119921
พบประเด็นหลายอย่างกับ dockershim ทำให้ตัดสินใจว่าจะให้ระบบซัพพอร์ต Docker เข้าสู่สถานะ deprecated และเตรียมถอดออกจาก Kubernetes ในอนาคต
ทีมงานที่ดูแล Kube เลยตัดสินใจเลิกใช้ Docker runtime แล้วให้ Kubelet คุยกับ containerd ตรงๆ ผ่าน CRI (Container Runtime Interface) ผลคือ container/pod จะสามารถทำงานได้เร็วขึ้นและกิน CPU/memory น้อยลง โดยไม่ผ่าน dockershim
*สาเหตุหลักที่ทางทีมเราได้เปลี่ยนก่อนที่อื่นๆ เพราะพบปัญหา Worker node สามารถรับ load ได้ประมาณ 250 Pods แล้วเกิดปัญหา Service kubelet คุยกับ docker แล้วได้ response time ช้ากว่า 3 นาที
## Error log จาก Kubelet
kubelet[30996]: I0629 16:13:44.951131 30996 setters.go:518] Node became not ready: {Type:Ready Status:False LastHeartbeatTime:2019–06–29 16:13:44.951049211 +0700 +07 m=+239038.614749639 LastTransitionTime:2019–06–29 16:13:44.951049211 +0700 +07 m=+239038.614749639 Reason:KubeletNotReady Message:PLEG is not healthy: pleg was last seen active 3m5.396071016s ago; threshold is 3m0s}
หลังจากพบปัญหาทางทีมเราเลย Research ว่ามี Kubernetes ลองรับ container-runtimes อะไรบ้าง (Ref . https://kubernetes.io/docs/setup/production-environment/container-runtimes/) ในนี้พวกเราเลือกที่จะใช้งาน cri-o มาใช้งานแทน docker เพราะ lightweight และถูกพัฒนามาใช้เฉพาะทาง
มีบทความการเปรียบเทียบ container-runtimes (docker-vs-cri-o-vs-containerd) อ่านต่อ
CRI-O คืออะไร
CRI-O เป็นการใช้งานของ Kubernetes CRI (อินเตอร์เฟสรันไทม์ของคอนเทนเนอร์) เพื่อเปิดใช้งานการใช้รันไทม์ที่เข้ากันได้ของ OCI (Open Container Initiative) มันเป็นทางเลือกที่มีน้ำหนักเบาในการใช้ Docker เป็นรันไทม์สำหรับ kubernetes จะช่วยให้ Kubernetes ใช้รันไทม์ที่เข้ากันได้กับ OCI ใด ๆ เป็นรันไทม์คอนเทนเนอร์สำหรับเรียกใช้ Pods อ่านต่อ


## How to migrate docker to crio
kubectl drain [node-name] --ignore-daemonsets
systemctl stop kubelet

## Remove docker and mount point on the worker node
docker ps -a -q|xargs -I{} docker stop {}
docker ps -a -q|xargs -I{} docker stop {}
docker ps -a -q|xargs -I{} docker rm {}
systemctl disable docker
systemctl stop docker
yum remove docker-ce -y
yum remove docker-ce-cli -y


## Step Install cri-o
- * เลือก CRI-O Version ให้เท่ากับ Kubernetes Version ในที่นี้ ผมเลือก (cri-o:1.18) มาทดสอบครับ
- Export env for crio install
export OS=CentOS_7
export VERSION=1.16
2. Add repo
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/devel:kubic:libcontainers:stable.repocurl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
Prerequisites and re-check your config
cat /etc/sysctl.d/99-sysctl.conf
net.ipv4.ip_forward=1
net.ipv4.ip_local_reserved_ports=30000–32767
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-arptables=1
net.bridge.bridge-nf-call-ip6tables=1
##If you don’t have that parameter let’s run step below
modprobe overlay
modprobe br_netfilter# Set up required sysctl params, these persist across reboots.
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
EOFsysctl --system
## Yum install
## Install & remove
yum install cri-o -y

## Configuration CRI-O โดยอ่านต่อที่ Document Link
vi /etc/sysconfig/crio
** ข้อมูลด้านล่างตัวอย่างเท่านั้น
# /etc/sysconfig/crio# use "--enable-metrics" and "--metrics-port value"
#CRIO_METRICS_OPTIONS="--enable-metrics"#CRIO_NETWORK_OPTIONS=
#CRIO_STORAGE_OPTIONS=CRIO_METRICS_OPTIONS=" --enable-metrics --metrics-port=9090"
CRIO_NETWORK_OPTIONS=" --cni-plugin-dir=/opt/cni/bin"
CRIO_STORAGE_OPTIONS=" --storage-driver=overlay"
CRIO_API_OPTIONES=" --listen=/var/run/crio/crio.sock"
CRIO_RUNTIME_OPTIONS=" --cgroup-manager=systemd --pids-limit=2048"##if you need out going to internet via proxy please uncomment#HTTP_PROXY=”http://proxy:80"
#HTTPS_PROXY=”http://proxy:80"
## config registry
vi /etc/containers/registries.conf unqualified-search-registries = ["docker.io"]

##Start CRI-O
sudo systemctl daemon-reload
sudo systemctl enable crio
sudo systemctl start crio
## know issue

Jan 22 14:55:11 k8s-master-lab-03 crio[96454]: time=”2021–01–22 14:55:11.074969255+07:00" level=fatal msg=”runtime config: invalid hooks_dir: stat /usr/share/containers/oci/hooks.d: no such file or directory: stat /usr/share/containers/oci/hooks.d: no such file or directory”
## Resolve by
mkdir -p /usr/share/containers/oci/hooks.d
##Test
sudo curl -v --unix-socket /var/run/crio/crio.sock http://localhost/info | jq

## Download crio-tool package
export VERSION="v1.16.0"
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz
sudo tar zxvf crictl-$VERSION-linux-amd64.tar.gz -C /usr/local/bin
rm -f crictl-$VERSION-linux-amd64.tar.gz
## verfity crictl
$crictl version
Version: 0.1.0
RuntimeName: cri-o
RuntimeVersion: 1.16.6
RuntimeApiVersion: v1alpha1$crictl pull nginx
Image is up to date for docker.io/library/nginx@sha256:0b159cd1ee1203dad901967ac55eee18c24da84ba3be384690304be93538bea8
## when you start kubelet found the error in below
systemctl start kubelet
systemctl status kubelet -l

- *Step ต่อไปเราต้องการแกะ Service kubelet ว่ามี Env ไป Connect Docker อยู่ส่วนไหน
systemctl status kubelet
##check all env file
EnvironmentFile=-/etc/kubernetes/kubelet.env
## ADD container-runtime=remote / container-runtime-endpoint=unix:///var/run/crio/crio.sock /cgroup-driver=systemd
KUBELET_ARGS="--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
--config=/etc/kubernetes/kubelet-config.yaml \
--kubeconfig=/etc/kubernetes/kubelet.conf \
--pod-infra-container-image=k8s.gcr.io/pause:3.1 \
--runtime-cgroups=/systemd/system.slice \
--container-runtime=remote \
--container-runtime-endpoint=unix:///var/run/crio/crio.sock \
--cgroup-driver=systemd \
***เปลี่ยน cgroup-driver เป็น systemd / container-runtime-endpoint เป็นใช้ crio.sock
Ref. https://github.com/cri-o/cri-o#getting-started
## Reload / restart
systemctl daemon-reload
systemctl start kubelet

## Verify Kubelet log
journalctl -fu kubelet
## Verify K8S node
kubectl get node -o wide

## Verify node and pods
kubectl get pod -A

Done!!!
ขอบคุณสำหรับแหล่งที่มาของข้อมูล
Ref.
https://cri-o.io/
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#configure-cgroup-driver-used-by-kubelet-on-control-plane-node
https://computingforgeeks.com/docker-vs-cri-o-vs-containerd/