Kaniko — Image Builder 試玩

Jan 27, 2022 Hao

Photo by Alvaro Reyes on Unsplash

Photo by Christina Rumpf on Unsplash

近年來受益於雲端蓬勃發展,Kubernetes 憑藉著其強大的功能逐漸成為了容器化應用的主流標準。微服務的概念也跟著 Kubernetes 的興起而普遍了起來,隨著微服務的普遍,容器的建置需求便益發重要。

在容器的建置中, Image 乃是不可獲缺的一環。沒有了 Image,任何的服務都是空談。既然 Image 如此重要,除了最傳統的 Docker build 來建立 Image 之外,我們是否還有其它的選擇?

雙子星身為雲原生運算基金會(Cloud Native Computing Foundation, CNCF)的會員之一,我們不斷地探索各種 CNCF Landscape 服務。 在此,本文將會試用 Kaniko,一個由 Google 所開發的 Image 建置工具,並且實際使用 kaniko 來建置雙子星的 Portal Product。

Why Kaniko?

Image 建置工具並非只有 Kaniko,其它較知名的有 BuildKit、img、orca-build……等。雖然都是建立 Image,但達成的手段都不太相同。

在 Kaniko 的 Github 上,Kaniko 明確地標榜著不需要依賴 Docker daemon 就可以解析 Dockerfile 的每個 command。

kaniko doesn’t depend on a Docker daemon and executes each command within a Dockerfile completely in userspace.

不依賴 Docker daemon 意味著你不需要 root 權限,這在那些可能沒辦法提供相關權限的環境裡特別有用,像是 Kubernetes cluster 就是一個很好的例子。

Kaniko 為什麼不需要 Docker daemon?

根據官方的解釋,Kaniko 會提取 Base image 中 filesystem,並且每當執行一個 Dockerfile 中的指令時,會去更改 filesystem 資料作一個快照,然後更新回 image metadata。

這也是為什麼不需要 Docker daemon 的原因,因為整個過程中並沒有牽涉到 Docker daemon。

測試環境

要使用 Kaniko 建立 Image 需要兩個條件:

  1. Build Context
  2. Kaniko Instance

Build Context 就是建立 Image 所需要的東西,舉例來說,像是 dockerfile、需要被編譯的檔案、png 圖檔……等會在 Image 裡面的東西。

Kaniko 提供了幾種方式存取你的 Build context:

再來是執行 Kaniko 的方式,Kaniko 同樣提供了幾種方法:

以下的範例我們會使用 Local Directory 來當作 Build Context,然後以Kubernetes cluster 的方式來執行。

測試

  1. 建立 Docker registry

筆者先於本地端的 Docker 中建立一個 Docker registry,以便接下來的 image 可以上傳到這個 registry 中。

$ docker run -d -p 5000:5000 — name registry registry:2.7

測試 Docker registry,確認可以正常運行。

$ curl localhost:5000/v2/_catalog 
{“repositories”:[]}
  1. 建立 Kaniko

共有三個 yaml 需要建立在 kubernetes,分別是 PV、PVC 及 Pod,需要指定自己的 namespace 及 Docker registry IP。 另外因為是上傳至本地端,所以也省略了 secret 的部份。

hostPath 指定路徑在 /data/kaniko ,並直接指定要掛載的 PVC

apiVersion: v1
kind: PersistentVolume
metadata:
  name: kaniko
  labels:
    type: local
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  claimRef:
    apiVersion: v1
    kind: PersistentVolumeClaim
    name: kaniko-claim
    namespace: <your namespace>
  storageClassName: local-storage
  hostPath:
    path: /data/kaniko
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: kaniko-claim
  namespace: <your namespace>
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 8Gi
  storageClassName: local-storage
apiVersion: v1
kind: Pod
metadata:
 name: kaniko
 namespace: <your namespace>
spec:
 nodeSelector:
   kubernetes.io/hostname: ubuntu3
 containers:
 — name: kaniko
   image: gcr.io/kaniko-project/executor:debug
   args: ["--dockerfile=/workspace/dockerfile",
           "--context=dir://workspace",
           "--destination=<your ip>:5000/ubuntu:test",
           "--insecure"]
   volumeMounts:
     — name: 
       mountPath: /workspace
 volumes:
   — name: kaniko-storage
     persistentVolumeClaim:
     claimName: kaniko-claim

然後還記得 Build Context 嗎?因為採用的是 Local Directory,我們必須把 dockerfile 放到 pv 的指定路徑 /data/kaniko 下,這樣 pod 才能在 volume 掛載的路徑 /workspace 讀到 dockerfile,並建立 Build Context。

FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]

建立資源

$ kubectl create -f pv.yaml
$ kubectl create -f pvc.yaml
$ kubectl create -f pod.yaml

  1. 檢查 image 有沒有上傳

建立 pod 以後,kaniko 就會開始執行 Build image 的工作,等到工作結束,我們就可以檢查一下 Docker registry 有沒有剛剛 kaniko 建置的 image

$ curl localhost:5000/v2/_catalog 
{“repositories”:[“ubuntu”]}
$ curl http://localhost:5000/v2/ubuntu/tags/list
{“name”:”ubuntu”,”tags”:[“test”]}

實際應用

依我們目前的 Image 產出流程,我們會先將 Portal Image 產出至某個 NFS 之後,再進行後續的流程。

因此,我們的需求有:

  1. Build Portal image
  2. 不需要上傳,只要將 Image 儲存成 tar 檔即可
  3. Image 需儲存至 NFS

這三點都不難解決,我們一個一個來看。

要產出 Portal Image 的話,我們的 Build Context 需要 portal resource,因此我們需要把 source code 也放在 /data/kaniko 底下。

再來,我們要怎麼把 Image 儲存成 tar 檔呢?

我們在 Kaniko 的官方 github 能夠找到可以下的參數,在這之中有一個參數是 tarPath,搭配另一個參數 no-push 就可以把 image 存成 tar 檔而不上傳。

最後儲存至 NFS,這個需求跟 kaniko 其實沒多大關係,只要系統 mount NFS 到指定地點即可。

根據以上需求,我們可以改寫 pod.yaml 檔如下:

spec.containers.args 加入上述參數,destination 指定 image 名稱, tarPath 指定儲存路徑, no-push 表示不上傳。

apiVersion: v1
kind: Pod
metadata:
  name: kaniko
  namespace: <your namespace>
spec:
  nodeSelector:
    kubernetes.io/hostname: ubuntu3
  containers:
  - name: kaniko
    image: gcr.io/kaniko-project/executor:debug
    args: ["--dockerfile=/workspace/dockerfile",
            "--context=dir://workspace",
            "--tarPath=/workspace/portal.tar",
            "--destination=portal:test",
            "--no-push"]
    volumeMounts:
      - name: kaniko-storage
        mountPath: /workspace
  restartPolicy: Never
  volumes:
    - name: kaniko-storage
      persistentVolumeClaim:

等到 kaniko 跑完之後,你就可以去確認 /data/kaniko 路徑上是否有產出 portal.tar 囉。

結語

kaniko 作為一個新興的 image builder,簡化了不少流程,可以直接 push image 到 registry 上,而且也解決了在 kubernetes 中建置 image 安全性的問題,讓我們可以安全的在 Kubernetes Build Image。 除此之外,gitlab 也內建支援 kaniko,如果是用 gitlab 作為主要 code repository 的話,在 gitlab 的 CI/CD 上也是一個不錯的整合方向。


雙子星雲端為 CNCF 會員,是 CNCF 所認證的 Kubernetes 服務提供商,在雲端技術擁有十多年以上的經驗,為台灣雲端技術早期領先者。目前為國家級 AI 雲的軟體及 Kubernetes 技術與服務提供商,更是諸多企業與單位導入容器與管理平台的最佳夥伴。 雙子星雲端除了既有的產品 AI Console 與 Gemini API Gateway 之外,也提供企業諮詢與導入雲原生與 Kubernetes 相關技術服務,協助企業擁抱 Cloud Natvive,達到數位轉型的目標。


相關文章

回雙子星技術部落格列表

Gemini AI Console

熱門文章


kubernetes professional service

關於我們

雙子星雲端是混合多雲技術的領導者,是國際認證之 KCSP - Kubernetes 服務提供商,同時也為 CNCF 雲原生計算基金會會員。

雙子星的雲端專家擁有 Kubernetes、OpenStack 與 Google Cloud Platform 等多項證照,我們的軟體至今已為上百家機構和數千台的 CPU/GPU 伺服器提供雲端服務。