前言
前兩篇文章我們探討了關於 kubernetes
中 Container Runtime
的概念,並且架設一個 kubernetes cluster
來使用 containerd
而非常見的 docker
作為其背後 Container Runtime
的解決方案。
然而如果你嘗試搜尋過關於 CRI
的文章·除了 kubernetes
,OCI
等相關概念關鍵字會出現外,你可能也有看過一個名為 cri-o
的關鍵字。
今天就要來跟大家聊聊 CRI-O
這個完全針對 kubernetes
環境開發的Container Runtime
解決方案。
介紹
我想直接透過一張圖來解釋 CRI-O
的角色與地位是最快且簡單的,透過與 docker
, containerd
等相關的比較,
該圖片從縱軸來看,有兩條主要的黑線,代表的是不同的標準架構,分別是 CRI
以及 OCI
。kubelet
本身透過 CRI
的介面與各式各樣相容於 CRI
的解決方案溝通,而這些解決方案最後都會透過符合 OCI
標準的 OCI runtime
去創造出真正的 Container
供使用者使用。
從上而下分別是之前介紹過 kubernetes
內與 docker
以及 contained
的架構演進圖。
kubelet
透過Dockershim
與docker engine
連接,最後一路串接到containerd
來創建container
。- 繞過
Docker
直接與後端的Containerd
溝通,為了滿足這個需求也需要一個額外的應用程式CRI-Containerd
來作為中間溝通的橋樑 - 隨者
containerd
1.1 版本的發行,CRI-Containerd
本身的功能已經可以透過plugin
的方式實現於containerd
中,可以再少掉一層溝通的耗損,這也是上一篇所介紹的安裝環境。 - 則是本篇所要介紹的重點
cri-o
, 一個完全針對kubernetes
需求的解決方案,讓整體的溝通變得更快速與簡單。
看完上述比較後會對 cri-o
有個初步的理解,知道其被設計出來的目的就是要提供更好地整合,減少多餘的 IPC
溝通,並且作為一個針對 kubernetes
設計的解決方案。
特色
CRI-O
的標題開宗明義直接闡明
CRI-O - OCI-based implementation of Kubernetes Container Runtime Interface
作為一個滿足 CRI
標準且能夠產生出相容於 OCI
標準 container
的解決方案,從整個設計到特色全部都是針對 kubernetes
來打造
- 本身的軟體版本與
kubernetes
一致,同時所有的測試都是基於 kubernetes 的使用去測試,確保穩定性。 - 目標是支援所有相容於
OCI Runtime
的解決方案,譬如Runc, Kata Containers
- 支援不同的
container image
,譬如docker
自己本身就有 schema 2/version 1 與 schema 2/version 2 - 使用
Container Network Interface CNI
來管理Container
網路
運作流程
整體的運作流程可以由下面這張圖片來說明
本圖擷取自cri-o
- kubelet 決定要創建一個
Pod
,於是透過gRPC
的方式發送基於CRI
標準的請求到cri-o
cri-o
基於containerts/image
的函式庫去該Pod
裡面描述的Container Image Registry
抓取該container image
- 下載下來的
container image
會被解開,接下來會透過containers/storage
相關的函式庫去處理container
本身的root filesystem
。 CRI-O
接者會使用OCI
提供的工具去產生一個用來描述該container
要如何運行的json
檔案。- 接者會根據設定去運行相容於
OCI Runtime
的解決方案來執行該container
. - 每一個
container
都會被獨立的 processconmon (container monitor)
給監控,處理者關於 pseudotty, log, 以及 exit code。 - 接下來會透過
CNI
的介面來幫該Pod
建立網路實際上 CNI 操作的對象是所謂的 infra container (pause container), 而非任何使用者請求的 container. 這部分會到 CNI 的章節在仔細介紹
整個 OCI
的概念相對於 docker, containerd
來得簡單,因為其目標就是支援 kubernetes
,不相干的功能不實作,專心提供更好的相容性與穩定性。
此外近來可以陸陸續續看到相關新聞在講述 CRI-O
的導入,譬如 OpenSuse/RedHat 都幫自家的產品導入 cri-o
並且作為預設的運行環境,就是希望能夠讓 kubernetes
的效能更好更穩定。
kubic.opensuse: CRI-O is now our default container runtime interface
Red Hat OpenShift Container Platform 4 now defaults to CRI-O as underlying container engine
看完了 cri-o
的概念介紹後,接下來我們仿造上篇 containerd
的概念一樣打造一樣的環境試試看,並且觀察相關的 process
運作。
安裝測試
安裝 CRI-O
基本上安裝的過程跟 containerd
大同小異,只是安裝的套件不同,同時最後設定 kubelet
的方式不同。
設定系統相關資訊
1 | modprobe overlay |
安裝套件
1 | apt-get update |
如果執行錯誤發現因為找不到相關的 /usr/local/libexec/crio/crio-wipe/crio-wipe.bash
這個檔案的話,可以手動幫忙建立個 soft link
1 | sudo ln -s /usr/libexec /usr/local/libexec |
這個問題在 github 上面已經被回報,但是不確定是什麼時候會修復到打包的 deb
之中,至少我2019/09/18
測試的時候還是壞掉的。
最後透過指令確認 cri-o 有正確運行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[email protected]:~$ sudo systemctl status cri-o
● crio.service - Container Runtime Interface for OCI (CRI-O)
Loaded: loaded (/usr/lib/systemd/system/crio.service; disabled; vendor preset: enabled)
Active: active (running) since Thu 2019-09-19 03:31:32 UTC; 20min ago
Docs: https://github.com/cri-o/cri-o
Main PID: 28333 (crio)
Tasks: 16
Memory: 870.2M
CPU: 28.468s
CGroup: /system.slice/crio.service
└─28333 /usr/bin/crio
Sep 19 03:31:32 k8s-dev systemd[1]: Starting Open Container Initiative Daemon...
Sep 19 03:31:32 k8s-dev systemd[1]: Started Open Container Initiative Daemon.
Sep 19 03:31:57 k8s-dev systemd[1]: Started Open Container Initiative Daemon.
Sep 19 03:32:10 k8s-dev systemd[1]: Started Container Runtime Interface for OCI (CRI-O).
安裝 kubernetes
安裝套件
安裝 kubeadm/kubelet/kubectl
相關檔案工具,不再撰述其過程1
2
3
4
5
6
7apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
接下來要使用 kubeadm
進行安裝·安裝步驟與之前 containerd
大同小異
由於部分需要的設定只能透過 config
的方式來修改,並不能像之前 containerd
的方式去改 systemd 裡面的環境變數,因此請增加 /etc/default/kubelet
這個檔案,內容如下1
2[email protected]:~$ cat /etc/default/kubelet
KUBELET_EXTRA_ARGS=--feature-gates="AllAlpha=false,RunAsGroup=true" --container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint='unix:///var/run/crio/crio.sock' --runtime-request-timeout=5m
建立叢集
透過下列指令依序建立叢集1
2
3
4
5
6
7sudo swapoff -a && sudo sysctl -w vm.swappiness=0
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml
kubectl taint nodes --all node-role.kubernetes.io/master-
如果 cri-o
沒有正確安裝的話,會因為找不到相關的 unix socket
,使得 kubelet
會嘗試去找 docker
來使用,但是因為我系統上面沒有 docker
,因此會使得安裝失敗,訊息如下。
1 | [email protected]:~$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 |
測試
因為 cri-o
就是完全針對 cri
+ kubernetes
打造的,所以前述的 crictl
相關的工具都還是可以繼續使用
1 | [email protected]:~$ sudo crictl images |
這時候透過 ps
等指令觀察一下系統中運行的指令1
2
3
4
5[email protected]:~$ sudo ps -x -awo command | grep cri
/usr/bin/crio
/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --feature-gates=AllAlpha=false,RunAsGroup=true --container-runtime=remote --cgroup-driver=systemd --container-runtime-endpoint=unix:///var/run/crio/crio.sock --runtime-request-timeout=5m
/usr/libexec/crio/conmon -s -c 014ba57340bf8afd3b2ce6982b760ffac82ce1bc2861a2b02f8069c8becde304 -n k8s_POD_kube-apiserver-k8s-dev_kube-system_b00230a3af5f91e5d10118aee4d054c4_0 -u 014ba57340bf8afd3b2ce6982b760ffac82ce1bc2861a2b02f8069c8becde304 -r /usr/lib/cri-o-runc/sbin/runc -b /var/run/containers/s
torage/overlay-containers/014ba57340bf8afd3b2ce6982b760ffac82ce1bc2861a2b02f8069c8becde304/userdata -p /var/run/containers/storage/overlay-containers/014ba57340bf8afd3b2ce6982b760ffac82ce1bc2861a2b02f8069c8becde304/userdata/pidfile -l /var/log/pods/kube-system_kube-apiserver-k8s-dev_b00230a3af5f91e5d10118aee4d054c4/014ba57340bf8afd3b2ce6982b760ffac82ce1bc2861a2b02f8069c8becde304.log --exit-dir /var/run/crio/exits --socket-dir-path /var/run/crio --log-level error --runtime-arg --root=/run/runc
可以觀察到
- 有一個名為
crio
的 daemon 運行 - kubelet 的參數都修改為去取
cri-o
配合 crio
本身會fork/exec
一個名為conmon
的 process ,也因為這個 跟kubernetes
是直接配合的,可以看到很多參數都直接跟kubernetes
有關,譬如名稱是k8s_POD_kube-apiserver-k8s-dev_kube-system_b00230a3af5f91e5d10118aee4d054c4_0
,裡面描述了其pod
的名稱,還有namespace
。
Summay
到這邊為止,我們已經架設過基於 containerd
與 cri-o
等不同相容於 CRI
的解決方案,唯一可惜的就是我們的背後都是基於 runc
這套純 container
的運行方式。
因此接下來的數天我們將針對這一塊去探討其他滿足 OCI Runtime
卻不同於 runc
的解決方案,特別會開始跟 Virtual Machine
牽扯到一起。
參考
- https://cri-o.io
- https://github.com/cri-o/cri-o/blob/master/tutorials/kubeadm.md
- https://www.opencontainers.org/blog/2018/06/20/cri-o-how-standards-power-a-container-runtime
- https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#configure-cgroup-driver-used-by-kubelet-on-master-node
- https://kubernetes.io/docs/setup/production-environment/container-runtimes/
個人資訊
我目前於 Hiskio 平台上面有開設 Kubernetes 相關課程,歡迎有興趣的人參考並分享,裡面有我從底層到實戰中對於 Kubernetes 的各種想法
組合包
https://hiskio.com/packages/7ey2vdnyN
疑難雜症除錯篇
https://hiskio.com/courses/440/about?promo_code=LG28Q5G
單堂(CI/CD)
https://hiskio.com/courses/385?promo_code=13K49YE&p=blog1
基礎概念
https://hiskio.com/courses/349?promo_code=13LY5RE
另外,歡迎按讚加入我個人的粉絲專頁,裡面會定期分享各式各樣的文章,有的是翻譯文章,也有部分是原創文章,主要會聚焦於 CNCF 領域
https://www.facebook.com/technologynoteniu
如果有使用 Telegram 的也可以訂閱下列頻道來,裡面我會定期推播通知各類文章
https://t.me/technologynote
你的捐款將給予我文章成長的動力