您好,登錄后才能下訂單哦!
如何創作一個自己的Helm Chart,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
我們平時在日常生活中會經常在不同的平臺上與各種各樣的應用打交道,比如從蘋果的 App Store 里下載的淘寶、高德、支付寶等應用,或者是在 PC 端安裝的 Word、Photoshop、Steam。這些各類平臺上的應用程序,對用戶而言,大多只需要點擊安裝就可使用。
然而,在云 (Kubernetes)上,部署一個應用往往卻不是那么簡單。如果想要部署一個應用程序到云上,首先要準備好它所需要的環境,打包成 Docker 鏡像,進而把鏡像放在部署文件 (Deployment) 中、配置服務 (Service)、應用所需的賬戶 (ServiceAccount) 及權限 (Role)、命名空間 (Namespace)、密鑰信息 (Secret)、可持久化存儲 (PersistentVolumes) 等資源。也就是編寫一系列互相相關的 YAML 配置文件,將它們部署在 Kubernetes 集群上。
但是即便應用的開發者可以把這些 Docker 鏡像存放在公共倉庫中,并且將所需的 YAML 資源文件提供給用戶,用戶仍然需要自己去尋找這些資源文件,并把它們一一部署。倘若用戶希望修改開發者提供的默認資源,比如使用更多的副本 (Replicas) 或是修改服務端口 (Port),他還需要自己去查需要在這些資源文件的哪些地方修改,更不用提版本變更與維護會給開發者和用戶造成多少麻煩了。
可見最原始的 Kubernetes 應用形態并不便利。
在這樣的大環境下,有一系列基于 Kubernetes 的應用包管理工具橫空出世。而我們今天的主角 Helm,就是這其中最受歡迎的選擇之一。
開發者按照 Helm Chart 的格式,將應用所需的資源文件包裝起來,通過模版化 (Templating) 的方式將一些可變字段(比如我們之前提到的暴露哪個端口、使用多少副本)暴露給用戶,最后將封裝好的應用包,也就是 Helm Chart,集中存放在統一的倉庫中供用戶瀏覽下載。
站在用戶角度,用戶只需要一行簡單的命令就可以完成應用的安裝、卸載與升級。對于安裝之后狀態,也可以通過 helm list
或者是原生的 kubectl 進行查詢。
$ helm install redis stable/redis $ kubectl get pods NAME READY STATUS RESTARTS AGE redis-master-0 1/1 Running 0 63s redis-slave-0-0 1/1 Running 0 63s redis-slave-1-0 1/1 Running 0 13s $ helm delete redis
那么站在開發者的角度上,我們應該如何去創作一個 Helm 應用包呢?
首先我們需要一個準備部署的鏡像。這個鏡像可以是一個 Java 程序、一個 Python 腳本、甚至是一個空的 linux 鏡像跑幾條命令。
這里我們使用一個簡單的基于 golang 的 hello world HTTP 服務。該服務通過讀取環境變量 USERNAME
獲得用戶自己定義的名稱,然后監聽 80 端口。對于任意 HTTP 請求,返回 Hello ${USERNAME}
。比如如果設置 USERNAME=world
(默認場景),該服務會返回 Hello world
。
然后我們使用 Dockerfile 對鏡像進行打包。先對 Golang 代碼進行編譯,然后將編譯后的程序放在基于 alpine 的鏡像中,以縮小鏡像體積。
在 Docker 構建好鏡像之后,我們把鏡像上傳到倉庫中,比如 Docker Hub 或是阿里云容器鏡像倉庫。準備工作做好之后,我們就可以開始創作 Helm Chart 了。
運行 helm create my-hello-world
,會得到一個 helm 自動生成的空 chart。這個 chart 里的名稱是 my-hello-world
。 需要注意的是,Chart 里面的 my-hello-world 名稱需要和生成的 Chart 文件夾名稱一致。如果修改 my-hello-world,則需要做一致的修改。 現在,我們看到 Chart 的文件夾目錄如下:
my-hello-world ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── NOTES.txt │ └── service.yaml └── values.yaml
在根目錄下的 Chart.yaml 文件內,聲明了當前 Chart 的名稱、版本等基本信息,這些信息會在該 Chart 被放入倉庫后,供用戶瀏覽檢索。比如我們可以把 Chart 的 Description 改成 "My first hello world helm chart"。在 Chart.yaml 里有兩個跟版本相關的字段,其中 version 指明的是 Chart 的版本,也就是我們應用包的版本;而 appVersion 指明的是內部實際使用的應用版本。
在 templates 文件夾內存放了各類應用部署所需要使用的 YAML 文件,比如 Deployment 和 Service。在我們當前的應用內,我們只需要一個 deployment,而有的應用可能包含不同組件,需要多個 deployments,那么我們就可以在 templates 文件夾下放置 deploymentA、deploymentB 等。同樣的,如果我們需要配置 serviceaccount, secret, volumes 等內容,也可以在里面添加相應的配置文件。
apiVersion: apps/v1beta2 kind: Deployment metadata: name: {{ template "my-hello-world.fullname" . }} labels: {{ include "my-hello-world.labels" . | indent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app.kubernetes.io/name: {{ include "my-hello-world.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} template: metadata: labels: app.kubernetes.io/name: {{ include "my-hello-world.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: USERNAME value: {{ .Values.Username }} ......
Helm Chart 對于應用的打包,不僅僅是將 Deployment 和 Service 以及其它資源整合在一起。我們看到 deployment.yaml 和 service.yaml 文件被放在 templates/ 文件夾下,相較于原生的 Kubernetes 配置,多了很多渲染所用的可注入字段。比如在 deployment.yaml 的 spec.replicas
中,使用的是 .Values.replicaCount
而不是 Kubernetes 本身的靜態數值。這個用來控制應用在 Kubernetes 上應該有多少運行副本的字段,在不同的應用部署環境下可以有不同的數值,而這個數值便是由注入的 Values
提供。
replicaCount: 1 image: repository: somefive/hello-world pullPolicy: IfNotPresent nameOverride: "" fullnameOverride: "" service: type: ClusterIP port: 80 ...... Username: AppHub
在根目錄下我們看到有一個 values.yaml
文件,這個文件提供了應用在安裝時的默認參數。在默認的 Values
中,我們看到 replicaCount: 1
,說明該應用在默認部署的狀態下只有一個副本。
為了使用我們要部署應用的鏡像,我們看到 deployment.yaml 中,在 spec.template.spec.containers
里, image
和 imagePullPolicy
都使用了 Values
中的值。其中 image
字段由 .Values.image.repository
和 .Chart.AppVersion
組成。
看到這里,同學們應該就知道需要變更的字段了:一個是位于 values.yaml 內的 image.repository
,另一個是位于 Chart.yaml 里的 AppVersion
。將它們與我們需要部署應用的 docker 鏡像匹配起來,這里我們把 values.yaml 里的 image.repository
設置成 somefive/hello-world
,把 Chart.yaml 里的 AppVersion
設置成 1.0.0
即可。
類似的,我們可以查看 service.yaml 內要部署的服務,其中的主要配置也在 values.yaml 中。默認生成的服務將 80 端口暴露在 Kubernetes 集群內部。我們暫時不需要對這一部分進行修改。
由于部署的 hello-world 服務會從環境變量中讀取 USERNAME
環境變量,所以將這個配置加入 deployment.yaml。
- name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: USERNAME value: {{ .Values.Username }}
現在我們的 deployment.yaml 模版會從 values.yaml 中加載 Username
字段,因此相應的,我們也在 values.yaml 中添加 Username: AppHub
。這樣,我們的應用就會從 values.yaml 中讀取 Username
,把它放入鏡像的環境變量中啟動了。
在準備好我們的應用后,我們可以使用 Helm lint 來粗略地檢查一下制作的 Chart 有沒有什么語法上的錯誤。如果沒有問題的話,就可以使用 helm package 命令對我們的 Chart 文件夾進行打包,打包后我們可以得到一個 my-hello-world-0.1.0.tgz 的應用包。這個便是我們完成的應用了。
$ helm lint --strict my-hello-world 1 chart(s) linted, 0 chart(s) failed [INFO] Chart.yaml: icon is recommended $ helm package my-hello-world
我們可以使用 helm install
命令嘗試安裝一下剛剛做好的應用包,然后用 kubectl 查看一下運行 pod 的狀態。通過 port-forward 命令將該 pod 的端口映射到本地端口上,這個時候就可以通過訪問 localhost 來訪問部署好的應用了。
$ helm install my-hello-world-chart-test my-hello-world-0.1.0.tgz $ kubectl get pods NAME READY STATUS RESTARTS AGE my-hello-world-chart-test-65d6c7b4b6-ptk4x-0 1/1 Running 0 4m3s $ kubectl port-forward my-hello-world-chart-test-65d6c7b4b6-ptk4x 8080:80 $ curl localhost:8080 Hello AppHub
有的同學可能會有疑惑,雖然我們應用開發者把可配置的信息暴露在 values.yaml 中,用戶使用應用的時候想要修改該怎么辦呢?答案很簡單,用戶只需要在 install 時使用 set 參數,設置想要覆蓋的參數即可。
應用開發者在 Chart 的 values 配置中只是提供了默認的安裝參數,用戶也可以在安裝時指定自己的配置。類似的,如果用戶可以用 upgrade 命令替代 install,實現在原有部署好的應用的基礎上變更配置。
$ helm install my-app my-hello-world-0.1.0.tgz --set Username="Cloud Native" $ helm install my-super-app my-hello-world-0.1.0.tgz -f my-values.yaml $ helm upgrade my-super-app my-hello-world-0.1.0.tgz -f my-new-values.yaml
我們注意到在安裝 Chart 指令運行后,屏幕的輸出會出現:
NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods -l "app=my-hello-world,release=my-hello-world-chart-test2" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80
這里的注釋是由 Chart 中的 templates/NOTES.txt
提供的。
我們注意到原始的 NOTES 中,所寫的 "app={{ template "my-hello-world.name" . }},release={{ .Release.Name }}"
和 deployment.yaml 中所寫的配置不太一樣,可以把它改成 "app.kubernetes.io/name={{ template "my-hello-world.name" . }},app.kubernetes.io/instance={{ .Release.Name }}"
,將 values.yaml 中的 version
更新成 0.1.1
。然后重新打包 Chart(運行 helm package
),得到新的 my-hello-world-0.1.1.tgz 之后,升級原有 Chart(運行 helm upgrade my-hello-world-chart-test2 my-hello-world-0.1.1.tgz --set Username="New Chart"
),就能看到更新過后的 NOTES 了。
NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods -l "app.kubernetes.io/name=my-hello-world,app.kubernetes.io/instance=my-hello-world-chart-test2" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80
那么制作完成的應用如何和其他人分享呢?Helm 官方推出的 ChartMuseum 提供了 Chart 倉庫的構建方法,使用它可以創建自己的 Chart 倉庫。然而自行維護一個倉庫本身成本不小,而且對于用戶而言如果每一個開發者都是自己的倉庫,他就需要將所需應用對應的倉庫都加入自己的檢索列表中,很不利于應用的傳播與分享。
我們團隊近期推出了開放云原生應用中心,Cloud Native App Hub,同步了各類應用,同時還提供了開發者上傳應用的渠道。
在我們的開放云原生應用中心中,應用來自兩個渠道:
一方面,我們定期從一些國外的知名 Helm 倉庫同步 Chart 資源,在同步的過程中,會對 Chart 內部使用的一部分 Docker 鏡像進行同步替換(例如 gcr.io 或者 quay.io 的鏡像),方便國內用戶訪問使用;
另一方面,我們和 Helm 官方庫一樣在 Github 上接受開發者通過 Pull Request 的形式提交自己的應用。提交成功的應用會在短期內同步至云原生應用中心,和其他官方應用展示在一起供其他用戶使用。
看完上述內容,你們掌握如何創作一個自己的Helm Chart的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。