[Kubernetes] Helm chart 的匯出匯入 (helm export import) 與離線安裝 (docker offline install)

Kubernetes (K8s) 已成為容器編排和管理的標準,Helm 作為 Kubernetes 的設定檔的套件管理器,可以簡化應用程式在 Kubernetes 叢集上的部署和設定檔的管理。然而,在某些場景下,我們可能需要在離線的 Kubernetes 環境中安裝或升級 Helm chart。本文將介紹如何使用 Helm 匯出和匯入 Chart 並進行離線安裝的步驟,給自己一個筆記也給想學習 K8s 的朋友一個指引。

Helm Chart 的安裝步驟與常用操作

我們就以 Flannel CNI 為例,講述一下 Helm Chart 的安裝步驟

文件裡安裝方式

$ helm repo add flannel https://flannel-io.github.io/flannel/

首先,先列出已下載的 Repo 有哪些,確定目標

$ helm repo list

你就會得到類似以下的列表

$ helm repo list
NAME                            URL
flannel                         https://flannel-io.github.io/flannel/

然後搜尋(列出)repo 裡面的內容

$ helm search repo flannel

列出一下當時寫文的搜尋結果

$ helm search repo flannel
NAME            CHART VERSION   APP VERSION     DESCRIPTION
flannel/flannel v0.25.1         v0.25.1         Install Flannel Network Plugin.

Step1. 〔有網路的下載主機〕下載相關檔案

helm 的匯出 (export) 是用 helm pull 的方式
它會在你當下的資料夾上面儲存一個 .tgz 檔案(就是 .tar.gz 啦)

$ helm pull <倉庫名稱>/<套件名稱>

例如

$ helm pull flannel/flannel --version v0.25.1

helm 的指令的設計跟別人比較不一樣
git pull 是從遠端 repository 倉庫拉取,更新本地 repository 整個線圖
docker pull 也是從 registry 倉庫拉取,更新本地的 image 版本
但 helm pull 是從遠端倉庫下載檔案回來,
它不是用 export 這個關鍵字而是用 pull 這是我覺得比較特別的地方

然後你就會得到一個 flannel.tgz 檔案,這個就是下載的內容了
但要注意,Helm 只儲存「設定檔模板」,也就是 Deployment, Service…等內容模板,
並沒有實際的 docker image,所以光只有 Helm Chart 沒有 image 是沒辦法在離線環境部署的。

Step2. 〔有網路的下載主機〕找尋 image

這個時候可以用兩種思路來找尋 image

  1. 實際找一個有網路的 K8s 叢集部署起來,再觀察會用到的 image
    這方式比較直接但也比較麻煩,但是需要有一個有網路的 K8s 叢集

  2. 拆開 Helm Chart 與 Values 找尋有關 image 記載的片段(這方式較推薦,以下也主要講這點)
    記載 image 的地方通常記載在 Deployment, DaemonSet 的地方
    而通常都會被拉成 Values 參數,這時候搜尋就可以了,也比較不會有遺漏

我們用 helm show values 匯出 values.yaml 設定檔,來找尋有關 image 的片段

# helm show values flannel/flannel > flannel-values.yaml

我們用 vi 打開該檔案 flannel-values.yaml

# vi flannel-values.yaml

在一般模式下打斜線 / 做搜尋,搜尋 image 關鍵字
就會找到類似的片段

flannel:
  image:
    repository: docker.io/flannel/flannel
    tag: v0.25.1
  image_cni:
    repository: docker.io/flannel/flannel-cni-plugin
    tag: v1.4.0-flannel1

然後稍加整理,就可以整理出

  • docker.io/flannel/flannel:v0.25.1
  • docker.io/flannel/flannel-cni-plugin:v1.4.0-flannel1

這二個 image

Step3. 〔有網路的下載主機〕下載 image

找到了 image 的 repository 跟 tag,就可以下載這個 image 了

$ docker pull flannel/flannel:v0.25.1
$ docker pull flannel/flannel-cni-plugin:v1.4.0-flannel1

註: docker.io 是 Docker Hub 的預設會帶的網址,所以可以省略

然後再用 docker savegzip 將 image 壓縮並儲存成 tar.gz 檔案

$ docker save flannel/flannel:v0.25.1 | gzip > image_flannel-v0.25.1.tar.gz
$ docker save flannel/flannel-cni-plugin:v1.4.0-flannel1 | gzip > image_flannel-cni-plugin-v1.4.0-flannel1.tar.gz

這樣就完成下載 image 的步驟了。
我是個人習慣會把 image 前面加上 image_ 的前綴,
避免跟其他備份檔,或者 Helm chart 搞混(因為結尾都是 .tar.gz

Step4. 〔無網路的目標主機〕載入 image

來到無網路的目標主機,這時候就可以將剛剛下載的 flannel.tgzimage_flannel-v0.25.1.tar.gzimage_flannel-cni-plugin-v1.4.0-flannel1.tar.gz 拷貝到目標主機上

4a. 有 Registry 的做法

我們先將 image 載入目標主機,我這邊是建議建一個私有的 Registry 來存放這些 image,這樣比較好管理
你可以用 Harbor, Nexus, Gitlab…等等來建立一個私有的 Registry

這邊假設 192.168.1.2 是你的私有 Registry 的 IP,請依照你的環境自行替換

$ docker load -i image_flannel-v0.25.1.tar.gz
$ docker tag flannel/flannel:v0.25.1 192.168.1.2/library/flannel:v0.25.1
$ docker push 192.168.1.2/library/flannel:v0.25.1

$ docker load -i image_flannel-cni-plugin-v1.4.0-flannel1.tar.gz
$ docker tag flannel/flannel-cni-plugin:v1.4.0-flannel1 192.168.1.2/library/flannel-cni-plugin:v1.4.0-flannel1
$ docker push 192.168.1.2/library/flannel-cni-plugin:v1.4.0-flannel1

這樣就把 image 推送到私有的 Registry 了。

替換掉 values 的內容

找尋 flannel-values.yaml 找到上次的片段

flannel:
  image:
    repository: docker.io/flannel/flannel
    tag: v0.25.1
  image_cni:
    repository: docker.io/flannel/flannel-cni-plugin
    tag: v1.4.0-flannel1

將它換成私有的 Registry

flannel:
  image:
    repository: 192.168.1.2/library/flannel
    tag: v0.25.1
  image_cni:
    repository: 192.168.1.2/library/flannel-cni-plugin
    tag: v1.4.0-flannel1

未來 K8s 在部署的時候就會從私有的 Registry 拉取 image 了。

4b. 無 Registry 的做法

如果沒有 Registry 的話,那就要辛苦一點,就只能用 docker load 來載入 image 了

注意,這個動作要在「所有」K8s 叢集的 node 節點上都要做,
因為 K8s 是會自動分配 Pod 到節點上的,所以要確保每個節點都有相同的 image
如果你有六台節點,那就要在六台伺服器主機上都要做這個動作

$ docker load -i image_flannel-v0.25.1.tar.gz
$ docker load -i image_flannel-cni-plugin-v1.4.0-flannel1.tar.gz

個人還是建議做一台私有 Registry 主機,這樣比較好管理

Step5. 〔無網路的目標主機〕安裝 Helm Chart

最後就是安裝 Helm Chart 了

以 Flannel 為例,在線版本的安裝指令是

$ helm install flannel --set podCidr="10.244.0.0/16" --namespace kube-flannel flannel/flannel

我們小小修改一下,改成離線安裝,指定離線 Helm chart 檔案的位置

$ helm install flannel \
--set podCidr="10.244.0.0/16" \
--set flannel.image.repository="docker.io/flannel/flannel" \
--set flannel.image.tag="v0.25.1" \
--set flannel.image_cni.repository="docker.io/flannel/flannel-cni-plugin" \
--set flannel.image_cni.tag="v1.4.0-flannel1" \
--namespace kube-flannel flannel.tgz

這樣可讀性比較差
推薦直接用剛剛修改好的 values.yaml

$ helm install flannel -n kube-flannel flannel.tgz -f flannel-values.yaml

沒意外的話,這樣就安裝成功了

希望這篇文章對你有幫助,謝謝你的閱讀。