玩K8S不得不會的HELM

一 基本概念

helm 相似於Linux系統下的包管理器,如yum/apt等,能夠方便快捷的將以前打包好的yaml文件快速部署進kubernetes內,方便管理維護。html

  • helm:一個命令行下客戶端工具,主要用於kubernetes應用chart的建立/打包/發佈已經建立和管理和遠程Chart倉庫。
  • Tiller:helm的服務端,部署於kubernetes內,Tiller接受helm的請求,並根據chart生成kubernetes部署文件(helm稱爲release),而後提交給 Kubernetes 建立應用。Tiller 還提供了 Release 的升級、刪除、回滾等一系列功能。
  • Chart: helm的軟件包,採用tar格式,其中包含運行一個應用所需的全部鏡像/依賴/資源定義等,還可能包含kubernetes集羣中服務定義
  • Release:在kubernetes中集羣中運行的一個Chart實例,在同一個集羣上,一個Chart能夠安裝屢次,每次安裝均會生成一個新的release。
  • Repository:用於發佈和存儲Chart的倉庫

簡單來講:node

  • helm的做用:像centos7中的yum命令同樣,管理軟件包,只不過helm這兒管理的是在k8s上安裝的各類容器。
  • tiller的做用:像centos7的軟件倉庫同樣,簡單說相似於/etc/yum.repos.d目錄下的xxx.repo。

二 組件架構

三 工做原理

3.1 Chart install

  • helm從制定目錄或tar文件解析chart結構信息
  • helm將制定的chart結構和value信息經過gRPC協議傳遞給tiller
  • tiller根據chart和values生成一個release
  • tiller經過json將release發送給kubernetes,生成release

3.2 Chart update

  • helm從制定的目錄或tar文件解析chart結構信息
  • helm將制定的chart結構和value信息經過gRPC協議傳給tiller
  • tiller生成release並更新制定名稱的release的history
  • tiller將release信息發送給kubernetes用於更新release

3.3 Chart Rollback

  • helm將會滾的release名稱傳遞給tiller
  • tiller根據release名稱查找history
  • tiller從history中獲取到上一個release
  • tiller將上一個release發送給kubernetes用於替換當前release

3.4 Chart處理依賴

Tiller 在處理 Chart 時,直接將 Chart 以及其依賴的全部 Charts 合併爲一個 Release,同時傳遞給 Kubernetes。所以 Tiller 並不負責管理依賴之間的啓動順序。Chart 中的應用須要可以自行處理依賴關係。mysql

四 安裝部署

4.1 v2版本安裝

4.1.1 安裝helm

# 在helm客戶端主機上,通常爲master主機
wget https://get.helm.sh/helm-v2.14.2-linux-amd64.tar.gz
tar xf helm-v2.14.2-linux-amd64.tar.gz
mv helm /usr/local/bin/
helm version
複製代碼

4.1.2 初始化tiller

  • 初始化tiller會自動讀取~/.kube目錄,因此須要確保config文件存在並認證成功linux

  • tiller配置rbac,新建rabc-config.yaml並應用git

# 在:https://github.com/helm/helm/blob/master/docs/rbac.md 能夠找到rbac-config.yaml

cat > rbac-config.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
EOF

kubectl apply -f rbac-config.yaml
複製代碼
  • 制定鏡像
docker pull jessestuart/tiller:v2.14.2

yum install socat
 # yum install socat

docker tag jessestuart/tiller:v2.14.2 gcr.io/kubernetes-helm/tiller:v2.14.2

helm init -i gcr.io/kubernetes-helm/tiller:v2.9.0
 # 須要注意點參數
–client-only:也就是不安裝服務端應用,這在 CI&CD 中可能須要,由於一般你已經在 k8s 集羣中安裝好應用了,這時只需初始化 helm 客戶端便可;
–history-max:最大歷史,當你用 helm 安裝應用的時候,helm 會在所在的 namespace 中建立一份安裝記錄,隨着更新次數增長,這份記錄會愈來愈多;
–tiller-namespace:默認是 kube-system,你也能夠設置爲其它 namespace;
複製代碼
  • 修改鏡像
# 因爲gfw緣由,能夠利用此鏡像https://hub.docker.com/r/jessestuart/tiller/tags
kubectl edit deployment -n kube-system tiller-deploy

image: jessestuart/tiller:v2.14.0
複製代碼
  • 異常處理
Error: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached: Get https://kubernetes-charts.storage.googleapis.com/index.yaml: read tcp 10.2.8.44:49020->216.58.220.208:443: read: connection reset by peer

解決方案:更換源:helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

而後在helm init


注意:tiller可能運行在node節點,將tiller鏡像下載到node節點並修改tag
複製代碼
  • 查看版本
[root@master ~]# helm version
Client: &version.Version{SemVer:"v2.14.2", GitCommit:"a8b13cc5ab6a7dbef0a58f5061bcc7c0c61598e7", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.14.2+unreleased", GitCommit:"d953c6875cfd4b351a1e8205081ea8aabad7e7d4", GitTreeState:"dirty"}
複製代碼

4.2 helm3 安裝部署

因爲國外不少鏡像網站國內沒法訪問,例如gcr.io ,建議使用阿里源,developer.aliyun.com/hub。github

AppHub 是一個託管在國內公有云上、全公益性的 Helm Hub 「中國站」,它的後端由阿里雲容器平臺團隊的三位工程師利用 20% 時間開發完成。redis

而這個站點的一個重要職責,就是把全部 Helm 官方 Hub 託管的應用自動同步到國內;同時,自動將 Charts 文件中的 gcr.io 等全部有網絡訪問問題的 URL 替換成爲穩定的國內鏡像 URL。sql

目前helm3已經不依賴於tiller,Release 名稱可在不一樣 ns 間重用。docker

4.2.1 安裝helm

Helm3 不須要安裝tiller,下載到 Helm 二進制文件直接解壓到 $PATH 下就可使用了。shell

cd /opt && wget https://cloudnativeapphub.oss-cn-hangzhou.aliyuncs.com/helm-v3.0.0-alpha.1-linux-amd64.tar.gz
tar -xvf helm-v3.0.0-alpha.1-linux-amd64.tar.gz
mv linux-amd64 helm3
mv helm3/helm helm3/helm3
chown root.root helm3 -R
cat > /etc/profile.d/helm3.sh << EOF
export PATH=$PATH:/opt/helm3
EOF
source /etc/profile.d/helm3.sh


[root@master helm3]# helm3 version
version.BuildInfo{Version:"v3.0.0-alpha.1", GitCommit:"b9a54967f838723fe241172a6b94d18caf8bcdca", GitTreeState:"clean"}
複製代碼

4.2.2 使用helm3安裝應用

helm repo add apphub https://apphub.aliyuncs.com
helm search guestbook
helm install guestbook apphub/guestbook
複製代碼

五 使用

5.1 基礎命令

http://hub.kubeapps.com/

completion 	# 爲指定的shell生成自動完成腳本(bash或zsh)
create     	# 建立一個具備給定名稱的新 chart
delete     	# 從 Kubernetes 刪除指定名稱的 release
dependency 	# 管理 chart 的依賴關係
fetch      	# 從存儲庫下載 chart 並(可選)將其解壓縮到本地目錄中
get        	# 下載一個命名 release
help       	# 列出全部幫助信息
history    	# 獲取 release 歷史
home       	# 顯示 HELM_HOME 的位置
init       	# 在客戶端和服務器上初始化Helm
inspect    	# 檢查 chart 詳細信息
install    	# 安裝 chart 存檔
lint       	# 對 chart 進行語法檢查
list       	# releases 列表
package    	# 將 chart 目錄打包成 chart 檔案
plugin     	# 添加列表或刪除 helm 插件
repo       	# 添加列表刪除更新和索引 chart 存儲庫
reset      	# 從集羣中卸載 Tiller
rollback   	# 將版本回滾到之前的版本
search     	# 在 chart 存儲庫中搜索關鍵字
serve      	# 啓動本地http網絡服務器
status     	# 顯示指定 release 的狀態
template   	# 本地渲染模板
test       	# 測試一個 release
upgrade    	# 升級一個 release
verify     	# 驗證給定路徑上的 chart 是否已簽名且有效
version    	# 打印客戶端/服務器版本信息
dep         # 分析 Chart 並下載依賴
複製代碼
  • 指定value.yaml部署一個chart
helm install --name els1 -f values.yaml stable/elasticsearch
複製代碼
  • 升級一個chart
helm upgrade --set mysqlRootPassword=passwd db-mysql stable/mysql

helm upgrade go2cloud-api-doc go2cloud-api-doc/ 
複製代碼
  • 回滾一個 chart
helm rollback db-mysql 1
複製代碼
  • 刪除一個 release
helm delete --purge db-mysql
複製代碼
  • 只對模板進行渲染而後輸出,不進行安裝
helm install/upgrade xxx --dry-run --debug
複製代碼

5.2 Chart文件組織

myapp/                               # Chart 目錄
├── charts                           # 這個 charts 依賴的其餘 charts,始終被安裝
├── Chart.yaml                       # 描述這個 Chart 的相關信息、包括名字、描述信息、版本等
├── templates                        # 模板目錄
│   ├── deployment.yaml              # deployment 控制器的 Go 模板文件
│   ├── _helpers.tpl                 # 以 _ 開頭的文件不會部署到 k8s 上,可用於定製通用信息
│   ├── ingress.yaml                 # ingress 的模板文件
│   ├── NOTES.txt                    # Chart 部署到集羣后的一些信息,例如:如何使用、列出缺省值
│   ├── service.yaml                 # service 的 Go 模板文件
│   └── tests
│       └── test-connection.yaml
└── values.yaml                      # 模板的值文件,這些值會在安裝時應用到 GO 模板生成部署文件
複製代碼

5.3 新建本身的Chart

  • 建立本身的mychart
[root@master mychart]# helm create mychart
Creating mychart
[root@master mychart]# ls
mychart
[root@master mychart]# tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml						# 部署相關資源
│   ├── _helpers.tpl							# 模版助手
│   ├── ingress.yaml							# ingress資源
│   ├── NOTES.txt									# chart的幫助文本,運行helm install展現給用戶
│   ├── service.yaml							# service端點
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 8 files
複製代碼
  • 刪除template下的全部文件,並建立configmap
rm -rf mychart/templates/*
# 咱們首先建立一個名爲 mychart/templates/configmap.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"
複製代碼
  • 安裝測試

因爲建立的yaml文件在template下,tiller讀取此文件,會將其發送給kubernetes。

[root@master mychart]# helm install ./mychart/
NAME:   enervated-dolphin
LAST DEPLOYED: Sun Jul 21 09:29:13 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME               DATA  AGE
mychart-configmap  1     0s

[root@master mychart]# kubectl get cm mychart-configmap
NAME                DATA   AGE
mychart-configmap   1      2m6s
[root@master mychart]# kubectl describe cm mychart-configmap
Name:         mychart-configmap
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
myvalue:
----
this is my chart configmap
Events:  <none>


[root@master mychart]# helm get manifest enervated-dolphin

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "this is my chart configmap"
複製代碼

helm get manifest 命令獲取 release 名稱(enervated-dolphin)並打印出上傳到服務器的全部 Kubernetes 資源。每一個文件都以 --- 開始做爲 YAML 文檔的開始,而後是一個自動生成的註釋行,告訴咱們該模板文件生成的這個 YAML 文檔。

從那裏開始,咱們能夠看到 YAML 數據正是咱們在咱們的 configmap.yaml 文件中所設計的 。

如今咱們能夠刪除咱們的 release:helm delete enervated-dolphin

[root@master mychart]# helm delete enervated-dolphin
release "enervated-dolphin" deleted
複製代碼

5.4 添加模版調用

硬編碼 name: 成資源一般被認爲是很差的作法。名稱應該是惟一的一個版本。因此咱們可能但願經過插入 release 名稱來生成一個名稱字段。

提示: name: 因爲 DNS 系統的限制,該字段限制爲 63 個字符。所以,release 名稱限制爲 53 個字符。Kubernetes 1.3 及更早版本僅限於 24 個字符(即 14 個字符名稱)。

修改下以前的configmap爲以下內容

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
複製代碼

name: 如今這個值發生了變化成了 {{.Release.Name}}-configmap

模板指令包含在 {{}} 塊中。

模板指令 {{.Release.Name}} 將 release 名稱注入模板。傳遞給模板的值能夠認爲是 namespace 對象,其中 dot(.)分隔每一個 namespace 元素。

Release 前面的前一個小圓點表示咱們從這個範圍的最上面的 namespace 開始(咱們將稍微談一下 scope)。因此咱們能夠這樣理解 .Release.Name:"從頂層命名空間開始,找到 Release 對象,而後在裏面查找名爲 Name 的對象"。

該 Release 對象是 Helm 的內置對象之一,稍後咱們將更深刻地介紹它。但就目前而言,這足以說明這會顯示 Tiller 分配給咱們發佈的 release 名稱。

如今,當咱們安裝咱們的資源時,咱們會當即看到使用這個模板指令的結果:

[root@master mychart]# helm install ./mychart/
NAME:   famous-peahen
LAST DEPLOYED: Sun Jul 21 09:42:05 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/ConfigMap
NAME                    DATA  AGE
famous-peahen-confgmap  1     0s


[root@master mychart]# helm get manifest famous-peahen

---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: famous-peahen-confgmap
data:
  myvalue: "this is my chart configmap"
複製代碼

咱們看過了基礎的模板:YAML 文件嵌入了模板指令,經過 。在下一部分中,咱們將深刻研究模板。但在繼續以前,有一個快速技巧可使構建模板更快:當您想測試模板渲染,但實際上沒有安裝任何東西時,可使用 helm install --debug --dry-run ./mychart。這會將 chart 發送到 Tiller 服務器,它將渲染模板。但不是安裝 chart,它會將渲染模板返回,以即可以看到輸出:

5.5 內置對象

helm內部變量

對象從模板引擎傳遞到模板中。你的代碼能夠傳遞對象(咱們將在說明 withrange 語句時看到示例)。甚至有幾種方法在模板中建立新對象,就像咱們稍後會看的 tuple 函數同樣。

對象能夠很簡單,只有一個值。或者他們能夠包含其餘對象或函數。例如,Release 對象包含多個對象(如 Release.Name)而且 Files 對象具備一些函數。

在上一節中,咱們使用 {{.Release.Name}} 將 release 的名稱插入到模板中。Release 是能夠在模板中訪問的頂級對象之一。

  • Release:這個對象描述了 release 自己。它裏面有幾個對象:
  • Release.Name:release 名稱
  • Release.Time:release 的時間
  • Release.Namespace:release 的 namespace(若是清單未覆蓋)
  • Release.Service:release 服務的名稱(始終是 Tiller)。
  • Release.Revision:此 release 的修訂版本號。它從 1 開始,每 helm upgrade 一次增長一個。
  • Release.IsUpgrade:若是當前操做是升級或回滾,則將其設置爲 true
  • Release.IsInstall:若是當前操做是安裝,則設置爲 true
  • Values:從 values.yaml 文件和用戶提供的文件傳入模板的值。默認狀況下,Values 是空的。
  • ChartChart.yaml 文件的內容。任何數據 Chart.yaml 將在這裏訪問。例如 {{.Chart.Name}}-{{.Chart.Version}} 將打印出來 mychart-0.1.0。chart 指南中 Charts Guide 列出了可用字段
  • Files:這提供對 chart 中全部非特殊文件的訪問。雖然沒法使用它來訪問模板,但可使用它來訪問 chart 中的其餘文件。請參閱 "訪問文件" 部分。
  • Files.Get 是一個按名稱獲取文件的函數(.Files.Get config.ini
  • Files.GetBytes 是將文件內容做爲字節數組而不是字符串獲取的函數。這對於像圖片這樣的東西頗有用。
  • Capabilities:這提供了關於 Kubernetes 集羣支持的功能的信息。
  • Capabilities.APIVersions 是一組版本信息。
  • Capabilities.APIVersions.Has $version 指示是否在羣集上啓用版本(batch/v1)。
  • Capabilities.KubeVersion 提供了查找 Kubernetes 版本的方法。它具備如下值:Major,Minor,GitVersion,GitCommit,GitTreeState,BuildDate,GoVersion,Compiler,和 Platform。
  • Capabilities.TillerVersion 提供了查找 Tiller 版本的方法。它具備如下值:SemVer,GitCommit,和 GitTreeState。
  • Template:包含有關正在執行的當前模板的信息
  • Name:到當前模板的 namespace 文件路徑(例如 mychart/templates/mytemplate.yaml
  • BasePath:當前 chart 模板目錄的 namespace 路徑(例如 mychart/templates)。

這些值可用於任何頂級模板。咱們稍後會看到,這並不意味着它們將在任何地方都要有。

內置值始終以大寫字母開頭。這符合Go的命名約定。當你建立本身的名字時,你能夠自由地使用適合你的團隊的慣例。一些團隊,如Kubernetes chart團隊,選擇僅使用首字母小寫字母來區分本地名稱與內置名稱。在本指南中,咱們遵循該約定。

5.6 values文件

在上一節中,咱們看了 Helm 模板提供的內置對象。四個內置對象之一是 Values。該對象提供對傳入 chart 的值的訪問。其內容來自四個來源:

  • chart 中的 values.yaml 文件
  • 若是這是一個子 chart,來自父 chart 的 values.yaml 文件
  • value 文件經過 helm install 或 helm upgrade 的 - f 標誌傳入文件(helm install -f myvals.yaml ./mychart
  • 經過 --set(例如 helm install --set foo=bar ./mychart

上面的列表按照特定的順序排列:values.yaml 在默認狀況下,父級 chart 的能夠覆蓋該默認級別,而該 chart values.yaml 又能夠被用戶提供的 values 文件覆蓋,而該文件又能夠被 --set 參數覆蓋。

值文件是純 YAML 文件。咱們編輯 mychart/values.yaml,而後來編輯咱們的 ConfigMap 模板。

刪除默認帶的 values.yaml,咱們只設置一個參數:

# 編輯values.yaml
domain: anchnet.com
 # 在模版中引用
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
  domain: {{.Values.domain}}
複製代碼

注意咱們在最後一行 {{ .Values.domain}} 獲取 domain` 的值。

[root@master mychart]# helm install --dry-run --debug ./mychart
'''
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: exciting-manta-confgmap
data:
  myvalue: "this is my chart configmap"
  domain: anchnet.com

複製代碼
  • 手動利用--set指定

因爲 domain 在默認 values.yaml 文件中設置爲 anchnet.com,這就是模板中顯示的值。咱們能夠輕鬆地在咱們的 helm install 命令中經過加一個 --set 添標誌來覆蓋:

helm install --dry-run --debug --set domain=51idc.com ./mychart 
'''
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: foppish-mule-confgmap
data:
  myvalue: "this is my chart configmap"
  domain: 51idc.com
複製代碼

因爲 --set 比默認 values.yaml 文件具備更高的優先級

  • 刪除默認 key

若是您須要從默認值中刪除一個鍵,能夠覆蓋該鍵的值爲 null,在這種狀況下,Helm 將從覆蓋值合併中刪除該鍵。

helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null
複製代碼

5.7 模版函數和管道

  • 模版函數

目前爲止,咱們已經知道如何將信息放入模板中。可是這些信息未經修改就被放入模板中。有時咱們想要轉換這些數據,使得他們對咱們來講更有用。

讓咱們從一個最佳實踐開始:當從. Values 對象注入字符串到模板中時,咱們引用這些字符串。咱們能夠經過調用 quote 模板指令中的函數來實現:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{quote .Values.favorite.drink}}
 food: {{quote .Values.favorite.food}}
複製代碼

模板函數遵循語法 functionName arg1 arg2...。在上面的代碼片斷中,quote .Values.favorite.drink 調用 quote 函數並將一個參數傳遞給它。

Helm 擁有超過 60 種可用函數。其中一些是由 Go 模板語言 Go template language 自己定義的。其餘大多數都是 Sprig 模板庫 Sprig template library 的一部分。在咱們講解例子進行的過程當中,咱們會看到不少。

雖然咱們將 Helm 模板語言視爲 Helm 特有的,但它其實是 Go 模板語言,一些額外函數和各類包裝器的組合,以將某些對象暴露給模板。Go 模板上的許多資源在瞭解模板時可能會有所幫助。

  • 管道

模板語言的強大功能之一是其管道概念。利用 UNIX 的一個概念,管道是一個連接在一塊兒的一系列模板命令的工具,以緊湊地表達一系列轉換。換句話說,管道是按順序完成幾件事情的有效方式。咱們用管道重寫上面的例子。

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | quote}}  food: {{.Values.favorite.food | quote}} 複製代碼

在這個例子中,沒有調用 quote ARGUMENT,咱們調換了順序。咱們使用管道(|)將 「參數」 發送給函數:.Values.favorite.drink | quote。使用管道,咱們能夠將幾個功能連接在一塊兒:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | quote}}  food: {{.Values.favorite.food | upper | quote}} 複製代碼

反轉順序是模板中的常見作法。你會看到.val | quotequote .val 更常見。練習也是。

當評估時,該模板將產生以下結果:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: trendsetting-p-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
複製代碼

請注意,咱們的原來 pizza 如今已經轉換爲 "PIZZA"

當有像這樣管道參數時,第一個評估(.Values.favorite.drink)的結果將做爲函數的最後一個參數發送。咱們能夠修改上面的飲料示例來講明一個帶有兩個參數的函數 repeat COUNT STRING

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | repeat 5 | quote}}  food: {{.Values.favorite.food | upper | quote}} 複製代碼

該 repeat 函數將回送給定的字符串和給定的次數,因此咱們將獲得這個輸出:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: melting-porcup-configmap
data:
 myvalue: "Hello World"
 drink: "coffeecoffeecoffeecoffeecoffee"
 food: "PIZZA"
複製代碼
  • 使用 default 函數

常用的一個函數是 defaultdefault DEFAULT_VALUE GIVEN_VALUE。該功能容許在模板內部指定默認值,以防該值被省略。讓咱們用它來修改上面的飲料示例:

drink: {{.Values.favorite.drink | default "tea" | quote}} 複製代碼

若是咱們像往常同樣運行,咱們會獲得咱們的 coffee:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: virtuous-mink-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
複製代碼

如今,咱們將從如下位置刪除喜歡的飲料設置 values.yaml:

favorite:
  #drink: coffee
 food: pizza
複製代碼

如今從新運行 helm install --dry-run --debug ./mychart 會產生這個 YAML:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: fair-worm-configmap
data:
 myvalue: "Hello World"
 drink: "tea"
 food: "PIZZA"
複製代碼

在實際的 chart 中,全部靜態默認值應該存在於 values.yaml 中,不該該使用該 default 命令重複(不然它們將是重複多餘的)。可是,default 命令對於計算的值是合適的,由於計算值不能在 values.yaml 中聲明。例如:

drink: {{.Values.favorite.drink | default (printf "%s-tea" (include "fullname" .)) }} 複製代碼

在一些地方,一個 if 條件可能比這 default 更適合。咱們將在下一節中看到這些。

模板函數和管道是轉換信息並將其插入到 YAML 中的強大方法。但有時候須要添加一些比插入字符串更復雜一些的模板邏輯。在下一節中,咱們將看看模板語言提供的控制結構。

  • 運算符函數

對於模板,運算符(eq,ne,lt,gt,and,or 等等)都是已實現的功能。在管道中,運算符能夠用圓括號(())分組。

將運算符放到聲明的前面,後面跟着它的參數,就像使用函數同樣。要多個運算符一塊兒使用,將每一個函數經過圓括號分隔。

{{/* include the body of this if statement when the variable .Values.fooString xists and is set to "foo" */}}
{{if and .Values.fooString (eq .Values.fooString "foo") }}
    {{...}}
{{end}}


{{/* do not include the body of this if statement because unset variables evaluate o false and .Values.setVariable was negated with the not function. */}}
{{if or .Values.anUnsetVariable (not .Values.aSetVariable) }}
   {{...}}
{{end}}
複製代碼

如今咱們能夠從函數和管道轉向流控制,條件,循環和範圍修飾符。

5.8 流程控制

5.8.1 流程控制

控制結構(模板說法中稱爲 「動做」)爲模板做者提供了控制模板生成流程的能力。Helm 的模板語言提供瞭如下控制結構:

  • if/else 用於建立條件塊
  • with 指定範圍
  • range,它提供了一個 「for each」 風格的循環

除此以外,它還提供了一些聲明和使用命名模板段的操做:

  • define 在模板中聲明一個新的命名模板
  • template 導入一個命名模板
  • block 聲明瞭一種特殊的可填寫模板區域

在本節中,咱們將談論 ifwithrange。其餘內容在本指南後面的 「命名模板」 一節中介紹。

5.8.2 if/else

咱們要看的第一個控制結構是用於在模板中有條件地包含文本塊。這就是 if/else 塊。

條件的基本結構以下所示:

{{if PIPELINE}}
  # Do something
{{else if OTHER PIPELINE}}
  # Do something else
{{else}}
  # Default case
{{end}}
複製代碼

注意,咱們如今討論的是管道而不是值。其緣由是要明確控制結構能夠執行整個管道,而不只僅是評估一個值。

若是值爲以下狀況,則管道評估爲 false。

  • 一個布爾型的假
  • 一個數字零
  • 一個空的字符串
  • 一個 nil(空或 null)
  • 一個空的集合(mapslicetupledictarray

在其餘狀況下, 條件值爲 true 此管道被執行。

咱們爲 ConfigMap 添加一個簡單的條件。若是飲料被設置爲咖啡,咱們將添加另外一個設置:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | default "tea" | quote}}  food: {{.Values.favorite.food | upper | quote}} {{if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{{ end }} 複製代碼

注意 .Values.favorite.drink 必須已定義,不然在將它與 「coffee」 進行比較時會拋出錯誤。因爲咱們在上一個例子中註釋掉了 drink:coffee,所以輸出不該該包含 mug:true 標誌。可是若是咱們將該行添加回 values.yaml 文件中,輸出應該以下所示:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: eyewitness-elk-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
 mug: true
複製代碼

5.8.3 控制空格

在查看條件時,咱們應該快速查看模板中的空格控制方式。讓咱們看一下前面的例子,並將其格式化爲更容易閱讀的格式:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | default "tea" | quote}}  food: {{.Values.favorite.food | upper | quote}} {{if eq .Values.favorite.drink "coffee"}}  mug: true
  {{end}}
複製代碼

最初,這看起來不錯。可是若是咱們經過模板引擎運行它,咱們會獲得一個錯誤的結果:

$ helm install --dry-run --debug ./mychart
SERVER: "localhost:44134"
CHART PATH: /Users/mattbutcher/Code/Go/src/k8s.io/helm/_scratch/mychart
Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: did not find expected key
複製代碼

發生了什麼?因爲上面的空格,咱們生成了不正確的 YAML。

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: eyewitness-elk-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
 mug: true
複製代碼

mug 不正確地縮進。讓咱們簡單地縮進那行,而後從新運行:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | default "tea" | quote}}  food: {{.Values.favorite.food | upper | quote}} {{if eq .Values.favorite.drink "coffee"}}  mug: true
  {{end}}
複製代碼

當咱們發送該信息時,咱們會獲得有效的 YAML,但仍然看起來有點意思:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: telling-chimp-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"

 mug: true
複製代碼

請注意,咱們在 YAML 中收到了一些空行。爲何?當模板引擎運行時,它將刪除 {{}} 中的空白內容,可是按原樣保留剩餘的空白。

YAML 中的縮進空格是嚴格的,所以管理空格變得很是重要。幸運的是,Helm 模板有幾個工具能夠幫助咱們。

首先,可使用特殊字符修改模板聲明的大括號語法,以告訴模板引擎填充空白。{{-(添加了破折號和空格)表示應該將格左移,而 -}} 意味着應該刪除右空格。注意!換行符也是空格!

確保 - 和其餘指令之間有空格。-3 意思是 「刪除左空格並打印 3」,而 -3 意思是 「打印 -3」。

使用這個語法,咱們能夠修改咱們的模板來擺脫這些新行:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | default "tea" | quote}}  food: {{.Values.favorite.food | upper | quote}} {{- if eq .Values.favorite.drink "coffee"}}  mug: true
  {{- end}}
複製代碼

爲了清楚說明這一點,讓咱們調整上面的內容,將空格替換爲 *, 按照此規則將每一個空格將被刪除。一個在該行的末尾的 * 指示換行符將被移除

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
 drink: {{.Values.favorite.drink | default "tea" | quote}}  food: {{.Values.favorite.food | upper | quote}}* **{{- if eq .Values.favorite.drink "coffee"}}  mug: true*
**{{- end}}
複製代碼

牢記這一點,咱們能夠經過 Helm 運行咱們的模板並查看結果:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: clunky-cat-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
 mug: true
複製代碼

當心使用 chomping 修飾符。這樣很容易引發意外:

 food: {{.Values.favorite.food | upper | quote}} {{- if eq .Values.favorite.drink "coffee" -}}  mug: true
  {{- end -}}
複製代碼

這將會產生 food: "PIZZA"mug:true,由於刪除了雙方的換行符。

有關模板中空格控制的詳細信息,請參閱官方 Go 模板文檔 Official Go template documentation

最後,有時候告訴模板系統如何縮進更容易,而不是試圖掌握模板指令的間距。所以,有時可能會發現使用 indent 函數({{indent 2 "mug:true"}})會頗有用。

5.8.4 使用 with 修改範圍

下一個要看的控制結構是 with。它控制着變量做用域。回想一下,. 是對當前範圍的引用。所以,.Values 告訴模板在當前範圍中查找 Values 對象。

其語法 with 相似於一個簡單的 if 語句:

{{with PIPELINE}}
  # restricted scope
{{end}}
複製代碼

範圍能夠改變。with 能夠容許將當前範圍(.)設置爲特定的對象。例如,咱們一直在使用的 .Values.favorites。讓咱們重寫咱們的 ConfigMap 來改變 . 範圍來指向 .Values.favorites

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
  {{- with .Values.favorite}}
 drink: {{.drink | default "tea" | quote}}  food: {{.food | upper | quote}} {{- end}} 複製代碼

注意,如今咱們能夠引用 .drink.food 無需對其進行限定。這是由於該 with 聲明設置 . 爲指向 .Values.favorite。在 {{end}}. 復位其先前的範圍。

可是請注意!在受限範圍內,此時將沒法從父範圍訪問其餘對象。例如,下面會報錯:

{{- with .Values.favorite}}
 drink: {{.drink | default "tea" | quote}}  food: {{.food | upper | quote}}  release: {{.Release.Name}}
  {{- end}}
複製代碼

它會產生一個錯誤,由於 Release.Name 它不在 . 限制範圍內。可是,若是咱們交換最後兩行,全部將按預期工做,由於範圍在 以後被重置。

{{- with .Values.favorite}}
 drink: {{.drink | default "tea" | quote}}  food: {{.food | upper | quote}} {{- end}}  release: {{.Release.Name}}
複製代碼

看下 range,咱們看看模板變量,它提供了一個解決上述範圍問題的方法。

5.8.5 循環 range 動做

許多編程語言都支持使用 for 循環,foreach 循環或相似的功能機制進行循環。在 Helm 的模板語言中,遍歷集合的方式是使用 range 操做子。

首先,讓咱們在咱們的 values.yaml 文件中添加一份披薩配料列表:

favorite:
 drink: coffee
 food: pizza
pizzaToppings:
 - mushrooms
 - cheese
 - peppers
 - onions
複製代碼

如今咱們有一個列表(模板中稱爲 slice)pizzaToppings。咱們能夠修改咱們的模板,將這個列表打印到咱們的 ConfigMap 中:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
  {{- with .Values.favorite}}
 drink: {{.drink | default "tea" | quote}}  food: {{.food | upper | quote}} {{- end}}  toppings: |-
    {{- range .Values.pizzaToppings}}
 - {{. | title | quote}} {{- end}} 複製代碼

讓咱們仔細看看 toppings:list。該 range 函數將遍歷 pizzaToppings 列表。但如今發生了一些有趣的事. 就像 withsets 的範圍 .range 操做子也是同樣。每次經過循環時,. 都設置爲當前比薩餅頂部。也就是第一次 . 設定 mushrooms。第二個迭代它設置爲 cheese,依此類推。

咱們能夠直接向管道發送 . 的值,因此當咱們這樣作時 {{. | title | quote}},它會發送 . 到 title(標題 case 函數),而後發送到 quote。若是咱們運行這個模板,輸出將是:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: edgy-dragonfly-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "PIZZA"
 toppings: |-
 - "Mushrooms"
 - "Cheese"
 - "Peppers"
 - "Onions"
複製代碼

如今,在這個例子中,咱們碰到了一些棘手的事情。該 toppings: |- 行聲明瞭一個多行字符串。因此咱們的 toppings list 實際上不是 YAML 清單。這是一個很大的字符串。咱們爲何要這樣作?由於 ConfigMaps 中的數據 data 由鍵 / 值對組成,其中鍵和值都是簡單的字符串。要理解這種狀況,請查看 Kubernetes ConfigMap 文檔.。但對咱們來講,這個細節並不重要。

YAML 中的 |- 標記表示一個多行字符串。這能夠是一種有用的技術,用於在清單中嵌入大塊數據,如此處所示。

有時能快速在模板中建立一個列表,而後遍歷該列表是頗有用的。Helm 模板有一個功能可使這個變得簡單:tuple。在計算機科學中,元組是類固定大小的列表類集合,可是具備任意數據類型。這粗略地表達了 tuple 的使用方式。

 sizes: |-
    {{- range tuple "small" "medium" "large"}}
 - {{.}}
    {{- end}}
 sizes: |-
 - small
 - medium
 - large
複製代碼

除了list和tuple以外,range還能夠用於遍歷具備鍵和值的集合(如mapdict)。當在下一節咱們介紹模板變量時,將看到如何作到這一點。

5.9 變量

咱們已經瞭解了函數,管道,對象和控制結構,咱們能夠在許多編程語言中找到更基本的用法之一:變量。在模板中,它們使用的頻率較低。咱們將看到如何使用它們來簡化代碼,並更好地使用 withrange

在前面的例子中,咱們看到這段代碼會失敗:

{{- with .Values.favorite}}
  drink: {{.drink | default "tea" | quote}}
  food: {{.food | upper | quote}}
  release: {{.Release.Name}}
  {{- end}}
複製代碼

Release.Name 不在該 with 塊中限制的範圍內。解決範圍問題的一種方法是將對象分配給能夠在不考慮當前範圍的狀況下訪問的變量。

在 Helm 模板中,變量是對另外一個對象的命名引用。它遵循這個形式 $name。變量被賦予一個特殊的賦值操做符::=。咱們可使用變量重寫上面的 Release.Name。

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
  {{- $relname := .Release.Name -}}
  {{- with .Values.favorite}}
  drink: {{.drink | default "tea" | quote}}
  food: {{.food | upper | quote}}
  release: {{$relname}}
  {{- end}}
複製代碼

注意,在咱們開始 with 塊以前,咱們賦值 $relname :=.Release.Name。如今在 with 塊內部,$relname 變量仍然指向發佈名稱。

會產生這樣的結果:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: viable-badger-configmap
data:
  myvalue: "Hello World"
  drink: "coffee"
  food: "PIZZA"
  release: viable-badger
複製代碼

變量在 range 循環中特別有用。它們能夠用於相似列表的對象以同時捕獲索引和值:

toppings: |-
    {{- range $index, $topping := .Values.pizzaToppings}}
      {{$index}}: {{ $topping }}
    {{- end}}
複製代碼

注意,range 首先是變量,而後是賦值運算符,而後是列表。這將分配整數索引(從零開始)給 $index,值給 $topping。運行它將產生:

 toppings: |-
      0: mushrooms
      1: cheese
      2: peppers
      3: onions
複製代碼

對於同時具備鍵和值的數據結構,咱們可使用 range 來得到二者。例如,咱們能夠對 .Values.favorite 像這樣循環:

apiVersion: v1
kind: ConfigMap
metadata:
 name: {{.Release.Name}}-configmap
data:
 myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite}}
  {{$key}}: {{ $val | quote }} {{- end}} 複製代碼

如今在第一次迭代中,$keydrink$valcoffee,第二次,$key 是 food,$val 會 pizza。運行上面的代碼會生成下面這個:

# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
 name: eager-rabbit-configmap
data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"
複製代碼

變量一般不是 「全局」 的。它們的範圍是它們所在的塊。以前,咱們在模板的頂層賦值 $relname。該變量將在整個模板的範圍內起做用。但在咱們的最後一個例子中,$key$val 只會在該 {{range...}}{{end}} 塊的範圍內起做用。

然而,總有一個變量是全局 $ 變量 - 這個變量老是指向根上下文。當你在須要知道 chart 發行名稱的範圍內循環時,這很是有用。

舉例說明:

{{- range .Values.tlsSecrets}}
apiVersion: v1
kind: Secret
metadata:
 name: {{.name}}
 labels:
    # Many helm templates would use `.` below, but that will not work,
    # however `$` will work here
    app.kubernetes.io/name: {{template "fullname" $}}
    # I cannot reference .Chart.Name, but I can do $.Chart.Name
    helm.sh/chart: "{{$.Chart.Name}}-{{ $.Chart.Version }}"
    app.kubernetes.io/instance: "{{$.Release.Name}}"
    app.kubernetes.io/managed-by: "{{$.Release.Service}}"
type: kubernetes.io/tls
data:
  tls.crt: {{.certificate}}
  tls.key: {{.key}}
---
{{- end}}
複製代碼

到目前爲止,咱們只查看了一個文件中聲明的一個模板。可是Helm模板語言的強大功能之一是它可以聲明多個模板並將它們一塊兒使用。咱們將在下一節中討論。

5.10 命名模版

如今是開始建立超過一個模板的時候了。在本節中,咱們將看到如何在一個文件中定義命名模板,而後在別處使用它們。命名模板(有時稱爲部分或子模板)是限定在一個文件內部的模板,並起一個名稱。咱們有兩種建立方法,以及幾種不一樣的使用方法。

在 「流量控制」 部分中,咱們介紹了聲明和管理模板三個動做:definetemplate,和 block。在本節中,咱們將介紹這三個動做,並介紹一個 include 函數,與 template 相似功能。

在命名模板時要注意一個重要的細節:模板名稱是全局的。若是聲明兩個具備相同名稱的模板,則最後加載一個模板是起做用的模板。因爲子 chart 中的模板與頂級模板一塊兒編譯,所以注意當心地使用特定 chart 的名稱來命名模板。

通用的命名約定是爲每一個定義的模板添加 chart 名稱:{{define "mychart.labels"}}。經過使用特定 chart 名稱做爲前綴,咱們能夠避免因爲同名模板的兩個不一樣 chart 而可能出現的任何衝突。

5.10.1 partials 和 _ 文件

到目前爲止,咱們已經使用了一個文件,一個文件包含一個模板。但 Helm 的模板語言容許建立指定的嵌入模板,能夠經過名稱訪問。

在咱們開始編寫這些模板以前,有一些文件命名約定值得一提:

  • 大多數文件 templates/ 被視爲包含 Kubernetes manifests
  • NOTES.txt 是一個例外
  • 名稱如下劃線(_)開頭的文件被假定爲沒有內部 manifest。這些文件不會渲染 Kubernetes 對象定義,而是在其餘 chart 模板中隨處可用以供調用。

這些文件用於存儲 partials 和輔助程序。事實上,當咱們第一次建立時 mychart,咱們看到一個叫作文件 _helpers.tpl。該文件是模板 partials 的默認位置。

5.10.2 用 definetemplate 聲明和使用模板

六 實戰

6.1 製做charts

  • 將用slate作好的go2cloud-api-doc 利用helm作成charts,方便後續部署
helm create go2cloud-api-doc

[root@master go2cloud-api-doc]# tree 
.
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

3 directories, 8 files
 # 配置 deployment
[root@master go2cloud_api_doc_charts]# egrep "^$|^#" -v go2cloud-api-doc/templates/deployment.yaml  
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "go2cloud-api-doc.fullname" . }}
  labels:
{{ include "go2cloud-api-doc.labels" . | indent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      imagePullSecrets: 
        - name: {{ .Values.imagePullSecrets }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.port }}
              protocol: TCP
          livenessProbe:
            {{- toYaml .Values.livenessProbe | nindent 12  }}
          readinessProbe:
            {{- toYaml .Values.readinessProbe | nindent 12  }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
 # 配置service
[root@master go2cloud_api_doc_charts]# egrep "^$|^#" -v go2cloud-api-doc/templates/service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: {{ include "go2cloud-api-doc.fullname" . }}
  labels:
{{ include "go2cloud-api-doc.labels" . | indent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: {{ .Values.service.port }}
      protocol: TCP
      name: http
      nodePort: {{ .Values.service.nodePort }}      
  selector:
    app.kubernetes.io/name: {{ include "go2cloud-api-doc.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
 # 配置values
[root@master go2cloud_api_doc_charts]# egrep "^$|^#|^[[:space:]]+#" -v go2cloud-api-doc/values.yaml
replicaCount: 1
image:
  repository: 10.234.2.218/go2cloud/go2cloud-api-doc
  tag: latest
  pullPolicy: Always
imagePullSecrets: registry-secret
nameOverride: ""
fullnameOverride: ""
service:
  type: NodePort
  port: 4567
  nodePort: 30567
ingress:
  enabled: false
  annotations: {}
  hosts:
    - host: chart-example.local
      paths: []
  tls: []
resources: 
  requests:
    cpu: 1000m
    memory: 1280Mi
  limits:
    cpu: 1000m
    memory: 1280Mi
livenessProbe:
  tcpSocket:
    port: 4567
  initialDelaySeconds: 10
  failureThreshold: 2 
  timeoutSeconds: 10
readinessProbe:
  httpGet:
    path: /#introduction
    port: http
  initialDelaySeconds: 5
  failureThreshold: 2 
  timeoutSeconds: 30
nodeSelector: {}
tolerations: []
affinity: {}

[root@master go2cloud_api_doc_charts]# egrep "^$|^#|^[[:space:]]+#" -v go2cloud-api-doc/Chart.yaml 
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: go2cloud-api-doc
version: 0.1.0
 # 部署
[root@master go2cloud_api_doc_charts]# helm install -n go2cloud-api-doc -f go2cloud-api-doc/values.yaml go2cloud-api-doc/                  
NAME:   go2cloud-api-doc
LAST DEPLOYED: Wed Jul 31 14:34:21 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Deployment
NAME              READY  UP-TO-DATE  AVAILABLE  AGE
go2cloud-api-doc  0/1    1           0          0s

==> v1/Pod(related)
NAME                               READY  STATUS             RESTARTS  AGE
go2cloud-api-doc-7cfb7bb795-clrz8  0/1    ContainerCreating  0         0s

==> v1/Service
NAME              TYPE      CLUSTER-IP     EXTERNAL-IP  PORT(S)         AGE
go2cloud-api-doc  NodePort  10.96.228.251  <none>       4567:30567/TCP  0s


NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services go2cloud-api-doc)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

[root@master go2cloud_api_doc_charts]# helm ls go2cloud-api-doc
NAME                    REVISION        UPDATED                         STATUS          CHART                   APP VERSION     NAMESPACE
go2cloud-api-doc        1               Wed Jul 31 14:34:21 2019        DEPLOYED        go2cloud-api-doc-0.1.0  1.0             default  

[root@master go2cloud_api_doc_charts]# kubectl get deployment go2cloud-api-doc
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
go2cloud-api-doc   0/1     1            0           10m

[root@master go2cloud_api_doc_charts]# kubectl get pods |grep go2cloud-api-doc
go2cloud-api-doc-7cfb7bb795-clrz8                         0/1     CrashLoopBackOff   7          10m

[root@master go2cloud_api_doc_charts]# kubectl get svc go2cloud-api-doc
NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
go2cloud-api-doc   NodePort   10.96.228.251   <none>        4567:30567/TCP   10m
 # 打包
[root@master go2cloud_api_doc_charts]# helm package ./go2cloud-api-doc/
Successfully packaged chart and saved it to: /data/go2cloud_api_doc_charts/go2cloud-api-doc-0.1.0.tgz
[root@master go2cloud_api_doc_charts]# tree 
.
├── go2cloud-api-doc
│   ├── charts
│   ├── Chart.yaml
│   ├── templates
│   │   ├── deployment.yaml
│   │   ├── _helpers.tpl
│   │   ├── NOTES.txt
│   │   ├── service.yaml
│   │   └── tests
│   │       └── test-connection.yaml
│   └── values.yaml
└── go2cloud-api-doc-0.1.0.tgz

4 directories, 8 files
 # 升級副本數量
helm upgrade go2cloud-api-doc --set replicaCount=2 go2cloud-api-doc/
複製代碼

6.2 配置minior

將製做好的charts存放到minio上,在k8s內部署minior

  • 建立本地chart目錄
mkdir minio-chart
複製代碼
  • 將修改好的chart文件打包
helm package redis
複製代碼
  • 將包拷貝至建立的本地chart目錄中
cp redis-8.0.5.tgz /root/minio-chart/
複製代碼
  • 更新/root/minio-chart/目錄下的index索引
helm repo index minio-chart/ --url http://10.234.2.204:31311/minio/common-helm-repo/
複製代碼

  • 將index.yaml 和chart包上傳至minio
mc cp index.yaml minio/common-helm-repo/
mc cp redis-8.0.5.tgz minio/common-helm-repo/
複製代碼
  • 將製做好的charts上傳至minio
helm repo add monocular https://helm.github.io/monocular
helm install -n monocular monocular/monocular

mc cp go2cloud-api-doc-0.1.0.tgz minio/common-helm-repo
複製代碼

能夠在${HOME}/.mc/config.json中查看ak密鑰信息。

  • 驗證

6.3 上傳至公共的helm倉庫

將製做好的charts包能夠上傳至helm倉庫,能夠放在本身的自建私有倉庫,流入:kubeapps/Monocular/minior等,能夠利用helm命令一鍵安裝。

上傳至公有云公共倉庫,例如國內的阿里目前建立的Apphub等,在現今的雲原生生態當中,已經有不少成熟的開源軟件被製做成了 Helm Charts,使得用戶能夠很是方便地下載和使用,好比 Nginx,Apache、Elasticsearch、Redis 等等。不過,在開放雲原生應用中心 App hub(Helm Charts 中國站) 發佈以前,國內用戶一直都很難直接下載使用這些 Charts。而如今,AppHub 不只爲國內用戶實時同步了官方 Helm Hub 裏的全部應用,還自動替換了這些 Charts 裏全部不可訪問的鏡像 URL(好比 gcr.io, quay.io 等),終於使得國內開發者經過 helm install 「一鍵安裝」應用成爲了可能。

具體提交本身的charts能夠參考:github.com/cloudnative…

此爲我上傳的slate chart,Slate helps you create beautiful, intelligent, responsive API documentation.

developer.aliyun.com/hub/detail?…

歡迎點贊。

七 相關連接

相關文章
相關標籤/搜索