目錄:
根據微服務的發版需求進行對應用進行調試,使用chart的模版發佈微服務
一、基於dubbo微服務發佈一個基於生產環境用到的helm模版
模版地址:git clone git@gitee.com:zhaocheng172/helm-dubbo.git
拉取請把你的公鑰給我,否則拉不下來css
3.6 Chart模板
Helm最核心的就是模板,即模板化的K8S manifests文件。
它本質上就是一個Go的template模板。Helm在Go template模板的基礎上,還會增長不少東西。如一些自定義的元數據信息、擴展的庫以及一些相似於編程形式的工做流,例如條件語句、管道等等。這些東西都會使得咱們的模板變得更加豐富。html
說在前面的話,其實在helm中,其實最關鍵的就是這個模版的渲染,咱們將yaml中可能常常變更的字段,去指定一個變量,這個變量就能夠經過helm的命令行,經過它的命名行去覆蓋它默認的變量,這就能動態的渲染到yaml中,裏面最重要的就是這個模版values,helm幫咱們作的事就是集中管理yaml,能動態的渲染這些yaml,由於在寫yaml時裏面可能會有不少字段,在後面部署的時候可能回有其餘變化,其實就是將這些變更的字段,動態的批量的去修改,以前沒有helm的時候,通常都是也會設計一個通用的模版來改變裏面常常變更的字段,通常就是使用sed來替換裏面的值,好比替換鏡像,將鏡像替換一個名字就能夠部署一個新的應用了,替換成功,apply一下就應用上了,固然這個鏡像是你提早將代碼編譯好的,而後經過dockerfile製做一個本身的鏡像,通常替換的鏡像地址也是harbor上的鏡像地址爲準,這樣的話,可能會寫不少替換的命令,顯然也不是很靈活,文件愈來愈多,對管理也是有必定成本,其實最好的方式有沒有在一個文件中,把這些變量字段寫進去,全部的yaml均可以讀到這個變量,把它引用到渲染的文件中,這也是helm要作的事,這也是helm核心的功能。java
一、模板
有了模板,咱們怎麼把咱們的配置融入進去呢?用的就是這個values文件。這兩部份內容其實就是chart的核心功能。
當咱們去部署一個應用的時候,好比發佈一個微服務,都是要作這麼一個chart,這個chart能夠來自於互聯網上,或者別人分享給你,或者本身製做的均可以,在這個chart中最核心的就是這個模版了,咱們去部署一個應用,它這個模版自己就是一個go的模版,用go去渲染的,只不過helm在go的基礎之上添寫了一些東西,讓它更靈活,好比條件判段
接下來,部署nginx應用,熟悉模板使用,先把templates 目錄下面全部文件所有刪除掉,這裏咱們本身來建立模板文件,語法的控制,都是知足這個模版更多的需求。node
好比先建立一個chart,一共4個目錄,在templates裏面就是咱們部署一個應用所需的配置yaml,像deployment,service,ingress等,咱們將一些常常變更的字段寫成變量的模式,經過values去定義這些變量的值,經過helm install建立的時候,它就會進行對values進行渲染到咱們的template裏面了,還有一個_helpers.tpl,它會放一些deployment,service都會用到的模版,好比都會用到一些通用的字段,那麼久能夠把它放到_helpers.tpl命名模版裏面,NOTES.txt是部署一個應用用到的一個提示,好比訪問的地址,還有一個test的這個目錄,好比你部署好一個應用,測試一下看看是否是部署正常。nginx
[root@k8s-master1 one_chart]# helm create one Creating one [root@k8s-master1 one_chart]# ls one [root@k8s-master1 one_chart]# cd one/ [root@k8s-master1 one]# ls charts Chart.yaml templates values.yaml [root@k8s-master1 one]# tree . . ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── NOTES.txt │ ├── serviceaccount.yaml │ ├── service.yaml │ └── tests │ └── test-connection.yaml └── values.yaml
先準備兩個yaml,而後咱們進行去對一些常常變的字段,進行渲染git
[root@k8s-master1 templates]# kubectl create deployment application --image=nginx --dry-run -o yaml > deployment.yaml [root@k8s-master1 templates]# kubectl expose deployment application --port=80 --target-port=80 --dry-run -o yaml > service.yaml
而後咱們將咱們的服務先發布出去測試一下,順便測試能不能正常訪問
咱們正常是經過apply -f 去發佈這樣的一個服務,如今使用helm來發布試一下,其實效果是同樣的,可是這樣去發佈的話,咱們跟apply -f 沒什麼效果了,而helm的核心應用的功能在於咱們可以有效的去渲染咱們的變量,使發佈咱們的微服務更靈活,好比就能夠經過模版進行變量的渲染修改一下鏡像的地址,發佈服務的名稱,以及副本數,等等,來動態的傳入,快速發佈多套微服務,簡單說就是部署一套通用的模版,來部署一些常規性的應用。docker
[root@k8s-master1 one_chart]# helm install application one/ NAME: application LAST DEPLOYED: Wed Dec 18 11:44:21 2019 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None [root@k8s-master1 templates]# kubectl get pod,svc NAME READY STATUS RESTARTS AGE pod/application-6c45f48b87-2gl95 1/1 Running 0 10s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/application ClusterIP 10.0.0.221 <none> 80/TCP 9s [root@k8s-master1 templates]# curl -I 10.0.0.221 HTTP/1.1 200 OK Server: nginx/1.17.6 Date: Wed, 18 Dec 2019 03:35:22 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 19 Nov 2019 12:50:08 GMT Connection: keep-alive ETag: "5dd3e500-264" Accept-Ranges: bytes
也就是部署一個chart,使用這個模版,可以部署一些常規性的應用,首先須要常常變更的是名字,還有副本,以及鏡像名稱編程
二、調試
Helm也提供了--dry-run 調試參數,幫助你驗證模板正確性。在執行helm install時候帶上這兩個參數就能夠把對應的values值和渲染的資源清單打印出來,而不會真正的去部署一個release。
好比咱們來調試上面建立的 chart 包:helm install pod-nodejs-tools --dry-run /root/one
vim
三、內置對象
{{ Release.Name}}這個屬於內置變量,這個內置變量其實就是咱們install的時候進行對咱們部署應用起的名字,也就是傳進來了,那麼就能夠直接使用這個來部署資源的名字
{{ Chart.Name}}這個值也是屬於helm的一個內置變量,這個也就是咱們建立chart後模版有Chart.yaml這個yaml,其實這個就是在這裏面去取的值,固然項目的名字,通常都是統一的,能夠直接經過{{ Values.name}}咱們本身去定義,也就是在values.yaml這個裏面去定義的
咱們編寫好了變量的傳輸以後,也能夠輸出一下,看看是否是可以正常輸出渲染
這裏的pod-base-common其實就會使我在{{ Release.name}}去生效 --dry-run就是預執行 ,one就是個人chart的目錄
像一些經常使用的release內置變量,Chart的變量能夠直接在chart包中去看到api
[root@k8s-master1 one]# cat templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: chart: {{ .Chart.Name }} app: {{ .Chart.Name }} name: {{ .Release.Name }} spec: replicas: {{ .Values.replicas }} selector: matchLabels: app: {{ .Values.label }} template: metadata: labels: app: {{ .Values.label }} spec: containers: - image: {{ .Values.image }}:{{ .Values.imagetag }} name: {{ .Release.Name }}
四、Values自定義變量
Values對象是爲Chart模板提供值,這個對象的值有4個來源:
chart 包中的 values.yaml 文件
父 chart 包的 values.yaml 文件
經過 helm install 或者 helm upgrade 的 -f或者 --values參數傳入的自定義的 yaml 文件
經過 --set 參數傳入的值[root@k8s-master1 one]# helm install pod-mapper-service --set replicas=1 ../one/
經過--set命令會優先將覆蓋values的值,建立一個副本,而不是二個了。
chart 的 values.yaml 提供的值能夠被用戶提供的 values 文件覆蓋,而該文件一樣能夠被 --set提供的參數所覆蓋。
[root@k8s-master1 one]# cat values.yaml replicas: 2 image: nginx imagetag: 1.16 label: nginx [root@k8s-master1 one_chart]# helm install pod-base-common --dry-run one/ [root@k8s-master1 ~]# helm install pod-css-commons /root/one_chart/one/ NAME: pod-css-commons LAST DEPLOYED: Wed Dec 18 14:41:02 2019 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None
執行以後查看渲染後的結果使用get manifest+項目的名稱,經過helm ls,就能查看到helm建立的服務
[root@k8s-master1 ~]# helm get manifest pod-css-commons [root@k8s-master1 one]# helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION pod-css-commons default 1 2019-12-18 14:41:02.800570406 +0800 CSTdeployed application-0.1.0 1.16.0
好比咱們再測試一下,好比咱們的代碼更新了,經過dockerfile又構成新的鏡像了,那麼咱們須要去替換新的鏡像,怎麼作?
其實講咱們的values下定義的名稱換成新的鏡像的地址就能夠了,這裏作演示寫的是nginx1.17
而後經過helm upgrade更換了新的鏡像
[root@k8s-master1 one]# helm upgrade pod-css-commons ../one/ Release "pod-css-commons" has been upgraded. Happy Helming! NAME: pod-css-commons LAST DEPLOYED: Wed Dec 18 15:00:14 2019 NAMESPACE: default STATUS: deployed REVISION: 2 TEST SUITE: None
經過get manifest能夠查看到渲染後的鏡像的地址,通常在微服務的發佈當中爲了保證項目名字的一致性,都是統一使用{{Values.name}},本身設置變量[root@k8s-master1 one]# helm get manifest pod-css-commons
好比如今有要發佈一個微服務
那麼咱們通常替換的通常就是服務的名字還有鏡像了
直接在values中去修改爲新的鏡像的地址還有項目的名字就--dry-run 一下測試沒問題直接發佈
[root@k8s-master1 one]# cat values.yaml replicas: 2 image: nginx imagetag: 1.15 name: pod-base-user-service app: pod-base-user-service port: 80 targetPort: 80 [root@k8s-master1 one]# helm install pod-base-user-service ../one/ [root@k8s-master1 one]# kubectl get pod NAME READY STATUS RESTARTS AGE nfs-client-provisioner-6f54fc894d-dbvmk 1/1 Running 0 5d3h pod-base-ec-service-664987f9c6-5f9vl 1/1 Running 0 7m18s pod-base-ec-service-664987f9c6-mw4jb 1/1 Running 0 7m18s pod-base-user-service-6b7d9d47b8-qqcbp 1/1 Running 0 7s pod-base-user-service-6b7d9d47b8-r5f96 1/1 Running 0 8s
五、管道與函數
剛纔的values,以及內置的對象其實就是將值傳給模板引擎進行渲染,另外模板引擎還支持對拿到數據進行二次處理,也就是必定非要使用values的值,也能夠對這個模版進行二次處理,好比我將拿到的數據,第一個字母爲大寫,或者我將拿到的值的字符串進行加個雙引號,那麼均可以對這個模版引擎進行二次處理,好比將拿到的值變成一個字符串,那麼這就用到了一個函數,那麼這個模版引擎支持這個函數,那麼這個函數不是特別的經常使用,可是也會用到這個,好比deployment這裏,好比labels這裏拿到這個值並加個雙引號,有的yaml的值必須加雙引號才能夠,其實這個實現的話也比較簡單,直接加一個quote就能夠
雙引號
labels: app: {{ quote .Values.name }}
測試效果已經給將雙引號給添加上了,其實這就是quote函數幫咱們作的一個二次處理,當咱們特定的給一些值加雙引號的時候,就能夠直接經過quote函數來實現
[root@k8s-master1 one]# helm install pod-tools-service --dry-run ../one/ labels: app: "pod-mapper-service"
再好比將一個特定的變量直接傳入,不經過values,我定義的env這個字段,默認是沒有的,經過{{ default "xxxx" .Values.env }} 傳入,好比這就是一個默認值,不須要變的,就能夠直接這麼定義
spec: nodeSelector: team: {{ .Values.team }} env: {{ default "JAVA_OPTS" .Values.env }}
那麼若是values裏面有這個值,它默認就會使用values裏面的值,若是沒有就會使用default使用默認的值
像縮進這一塊,自己yaml就是以層級關係來定義的,那麼有時候咱們就會用到這種的需求來渲染咱們的層級關係
其餘函數:
縮進:{{ .Values.resources | indent 12 }} 大寫:{{ upper .Values.resources }} 首字母大寫:{{ title .Values.resources }}
六、流程控制
流程控制是爲模板提供了一種能力,知足更復雜的數據邏輯處理。
Helm模板語言提供如下流程控制語句:
if/else 條件塊
with 指定範圍
range 循環塊
像縮進流程控制通常也都會用到,像else/if了都會作一下複雜邏輯的處理,
values下定義這個參數
test: "123"
templates/deployment.yaml下去定義這個判斷,if test=123,那麼就輸出test:a,不然若是變量的值爲其餘,這裏就打印test:b了,這種的應用的場景也能根據本身的實際應用場景對yaml進行定義,可是這種遇到的狀況也很少。
spec: nodeSelector: team: {{ .Values.team }} env: {{ default "JAVA_OPTS" .Values.env }} {{ if eq .Values.test "123" }} test: a {{ else }} test: b {{ end }}
其實在這裏輸出的話,給留出空格,其實就是剛纔的{{咱們定義的參數留下的}},這個直接去掉就能夠了,經過-就能夠刪除
eq運算符判斷是否相等,另外還支持ne、 lt、 gt、 and、 or等運算符。
{{- if eq .Values.test "123" }} test: a {{- else }} test: b {{- end }} containers:
條件判斷就是判斷條件是否爲真,若是值爲如下幾種狀況則爲false:
一個布爾類型的 爲flase
一個數字 零
一個 空的字符串
一個 nil(空或 null)
一個空的集合( map、 slice、 tuple、 dict、 array)
除了上面的這些狀況外,其餘全部條件都爲 真。
好比values的值設置的就是flase,那就不爲真
或者就是values的值設置的就是0,那麼默認也是設置爲false,那也不爲真
若是爲空,那麼也爲false,或者爲集合,以上的狀況都爲false
那麼咱們在values設置一個0,測試一下,而後這邊打印的爲b,說明就是假的
test: 0 test: "" [root@k8s-master1 one]# helm install pod-mapper-service --dry-run ../one/ spec: nodeSelector: team: team1 env: JAVA_OPTS test: b containers: - image: nginx:1.15 name: pod-mapper-service
如今咱們使用它們helm官方原來的values的模版來建立一個應用並且它這個支持序列化的格式化的結構,好比鏡像image,可能會有他的鏡像的地址標籤名字,可能下面還定義多個屬性,因此這種就能夠定義這種結構化的一個格式,好比像倉庫的地址,拉取鏡像的策略
image: repository: nginx tag: 1.17 pullPolicy: IfNotPresent
[root@k8s-master1 one]# cat templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.name }} template: metadata: labels: app: {{ .Values.name }} spec: nodeSelector: team: {{ .Values.team }} containers: - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} name: {{ .Values.name }}
[root@k8s-master1 one]# cat templates/service.yaml apiVersion: v1 kind: Service metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: ports: - port: {{ .Values.port }} protocol: TCP targetPort: {{ .Values.port }} selector: app: {{ .Values.name }}
[root@k8s-master1 one]# vim values.yaml app: pod-base-jss name: pod-base-jss replicaCount: 3 image: repository: nginx tag: 1.17 pullPolicy: IfNotPresent team: team3 [root@k8s-master1 one]# helm install pod-base-jss ../one/ [root@k8s-master1 one]# helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION pod-base-jss default 1 2019-12-19 13:57:49.881954736 +0800 CST deployed application-0.1.0
如今再增長一個資源限制
作一個判斷當默認爲false或者true的狀況下,作相關的動做,就是說資源限制用不用,若是定義的爲false,那麼就不使用這裏面的資源,那麼爲ture的話,就使用,或者不設置,將限制的資源註釋去掉
如今就去判斷這個resource是否是爲真,若是爲真的話就使用resource,而後對這個pod多一個資源的限制,若是爲假的話,就不作資源限制,直接判斷{{ if .Values.resources }}
這裏我先判斷爲真測試一下,它會將咱們的判斷爲真的加進去
[root@k8s-master1 one]# cat templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.name }} template: metadata: labels: app: {{ .Values.name }} spec: nodeSelector: team: {{ .Values.team }} containers: - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} name: {{ .Values.name }} {{- if .Values.resources }} resources: limits: cpu: {{ .Values.resources.limits.cpu }} memory: {{ .Values.resources.limits.memory}} requests: cpu: {{ .Values.resources.requests.cpu }} memory: {{ .Values.resources.requests.memory }} {{- else }} resources: {} {{- end }}
這裏就會去引用咱們下面的變量,若是沒這個需求就能夠直接在resources: 0 ,或者""或者false均可以,而後將下面的註釋就不會引用了,也就是至關於一個開關,很好的去管理咱們的應用
[root@k8s-master1 one]# cat values.yaml resources: limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi
測試結果查看
[root@k8s-master1 one]# helm upgrade pod-base-jss --dry-run ../one/ Release "pod-base-jss" has been upgraded. Happy Helming! NAME: pod-base-jss LAST DEPLOYED: Thu Dec 19 14:36:37 2019 NAMESPACE: default STATUS: pending-upgrade REVISION: 2 TEST SUITE: None HOOKS: MANIFEST: --- Source: application/templates/service.yaml apiVersion: v1 kind: Service metadata: labels: app: pod-base-jss name: pod-base-jss spec: ports: - port: 80 protocol: TCP targetPort: 80 selector: app: pod-base-jss --- Source: application/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: pod-base-jss name: pod-base-jss spec: replicas: 3 selector: matchLabels: app: pod-base-jss template: metadata: labels: app: pod-base-jss spec: nodeSelector: team: team3 containers: - image: nginx:1.17 name: pod-base-jss resources: limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi
或者還有一種方法,直接在values加入enabled,false就是關閉的意思,執行以後首先會根據enabeld去使用
resources: enabled: false limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi
那麼在{{ if .Values.resource.enabled}} 去定義將values的開關爲true就就會使用,爲false就不會使用
[root@k8s-master1 one]# cat templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.name }} template: metadata: labels: app: {{ .Values.name }} spec: nodeSelector: team: {{ .Values.team }} containers: - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} name: {{ .Values.name }} {{- if .Values.resources.enabled }} resources: limits: cpu: {{ .Values.resources.limits.cpu }} memory: {{ .Values.resources.limits.memory}} requests: cpu: {{ .Values.resources.requests.cpu }} memory: {{ .Values.resources.requests.memory }} {{- else }} resources: {} {{- end }}
像這樣的需求也不少,有的微服務不須要去建立ingress的,有的可能須要,或者有的可能不使用ingress做爲集羣外部的負載均衡器流入到集羣內部的你的服務上,直接使用service的clusterIP再部署幾臺nginx負載均衡器來進行負責轉發內部的服務,經過slb進行暴露出去,那麼咱們去實現一下這兩個需求
在values中它有這個模版enabled能夠跟剛纔的也同樣,若是設置爲false的話就不建立ingress規則,若是爲true的話就建立這個規則
先對service進行定義,也就是流程控制,如今對service不進行使用
values進行設置開關爲false,enabled
[root@k8s-master1 one]# cat values.yaml app: pod-base-tools name: pod-base-tools replicaCount: 3 image: repository: nginx tag: 1.17 pullPolicy: IfNotPresent serviceAccount: create: true name: service: enabled: false port: 80 targetPort: 80 ingress: enabled: false annotations: {} hosts: - host: chart-example.local paths: [] tls: [] resources: enabled: true limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi nodeSelector: team: team2
[root@k8s-master1 templates]# cat service.yaml {{- if .Values.service.enabled }} apiVersion: v1 kind: Service metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: ports: - port: {{ .Values.service.port }} protocol: TCP targetPort: {{ .Values.service.targetPort }} selector: app: {{ .Values.name }} {{ end }} [root@k8s-master1 templates]# cat deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.name }} template: metadata: labels: app: {{ .Values.name }} spec: nodeSelector: team: {{ .Values.nodeSelector.team }} containers: - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} name: {{ .Values.name }} {{- if .Values.resources.enabled }} resources: limits: cpu: {{ .Values.resources.limits.cpu }} memory: {{ .Values.resources.limits.memory}} requests: cpu: {{ .Values.resources.requests.cpu }} memory: {{ .Values.resources.requests.memory }} {{- else }} resources: {} {{- end }}
執行以後不會建立service,由於我設置的if去判斷爲假的話,那麼就不建立service,並設置的開關爲false,那麼設置爲true就直接能夠建立service了[root@k8s-master1 templates]# helm install pod-base-tools --dry-run ../../one/
如今建立一個ingress,也設置一個開關,其實方法也是同樣的
[root@k8s-master1 one]# cat values.yaml app: pod-base-user name: pod-base-user replicaCount: 3 image: repository: nginx tag: 1.17 pullPolicy: IfNotPresent serviceAccount: create: true name: service: enabled: false port: 80 targetPort: 80 ingress: enabled: true annotations: {} hosts: - host: chart-example.local paths: [] tls: [] resources: enabled: true limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi nodeSelector: team: team2
[root@k8s-master1 templates]# cat ingress.yaml {{- if .Values.ingress.enabled }} apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: test-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80 {{ end }} [root@k8s-master1 templates]# helm install pod-base-user ../../one/ [root@k8s-master1 templates]# kubectl get ing NAME HOSTS ADDRESS PORTS AGE ingress.extensions/test-ingress * 80 39s
with
with :控制變量做用域。
{{.Release.xxx}}或者 {{.Values.xxx}}其中的 .就是表示對當前範圍的引用, .Values就是告訴模板在當前範圍中查找 Values對象的值。而 with語句就能夠來控制變量的做用域範圍,其語法和一個簡單的 if語句比較相似
一個小問題就是當咱們去寫變量引用的時候都會在前面加一個.這個點的意思就是從哪一個範圍去找,按照.的話,就是按這個生成模版的結構去找的
再使用一下nodeSelector這個值吧,這個看實際的場景,通常呢都是會設置調度的節點進行分組,這樣才保證咱們更好的去管理node節點的分佈微服務的佈局
這個呢也可使用以前的語法if去作判斷
也能夠經過這個開關的方式進行配置,或者就是with的方式,或者就是toyaml的函數方式
spec: {{- if .Values.nodeSelector.enabled }} nodeSelector: team: {{ .Values.nodeSelector.team }} {{- else }} {{- end }}
[root@k8s-master1 one]# cat values.yaml nodeSelector: enabled: true team: team2 [root@k8s-master1 templates]# cat deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: {{ .Values.name }} name: {{ .Values.name }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.name }} template: metadata: labels: app: {{ .Values.name }} spec: {{- if .Values.nodeSelector.enabled }} nodeSelector: team: {{ .Values.nodeSelector.team }} {{- else }} {{- end }} containers: - image: {{ .Values.image.repository }}:{{ .Values.image.tag }} name: {{ .Values.name }} {{- if .Values.resources.enabled }} resources: limits: cpu: {{ .Values.resources.limits.cpu }} memory: {{ .Values.resources.limits.memory}} requests: cpu: {{ .Values.resources.requests.cpu }} memory: {{ .Values.resources.requests.memory }} {{- else }} resources: {} {{- end }}
或者把開關去掉,用with直接去讀取咱們的參數也是能夠的
[root@k8s-master1 one]# tail -4 values.yaml nodeSelector: team: team2
在deployment去定義這個字段,- with 指定.team,來讀取相應的值
spec: {{- with .Values.nodeSelector }} nodeSelector: team: {{ .team }} {{- else }} {{- end }}
使用toYaml方式
spec: {{- with .Values.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} {{- end }}
with是一個循環構造。使用.Values.nodeSelector中的值:將其轉換爲Yaml。
toYaml以後的點是循環中.Values.nodeSelector的當前值
range
在 Helm 模板語言中,使用 range關鍵字來進行循環操做。
咱們在 values.yaml文件中添加上一個變量列表:
像range通常要寫多個元素的時候要使用,像toyaml和with通常用於結構化的層次比較多的,比較使用env這樣的適合使用range,
cat values.yaml test: - 1 - 2 - 3
循環打印該列表:
apiVersion: v1 kind: ConfigMap metadata: name: {{ .Release.Name }} data: test: | {{- range .Values.test }} {{ . }} {{- end }}
循環內部咱們使用的是一個 .,這是由於當前的做用域就在當前循環內,這個 .引用的當前讀取的元素
七、變量
變量,在模板中,使用變量的場合很少,但咱們將看到如何使用它來簡化代碼,並更好地利用with和range。由於剛纔咱們用到的with,不能在下面再去定義其餘的變量了,那麼怎麼在with中去引用一些全值內置的變量呢,有兩種方法,一個是使用helm的變量賦值進行去使用,第二種是使用$去使用
測試一下,先不添加$
spec: {{- with .Values.nodeSelector }} nodeSelector: app: {{ .Values.name }}
執行結果是這樣的
[root@k8s-master1 templates]# helm install pod-base-user --dry-run ../../one/ Error: template: application/templates/deployment.yaml:19:23: executing "application/templates/deployment.yaml" at <.Values.name>: nil pointer evaluating interface {}.name
那麼加上$的話這樣就會正常輸出
spec: nodeSelector: app: pod-base-user team: team2
也可使用另一種形式來輸出
spec: {{- $releaseName := .Release.Name -}} {{- with .Values.nodeSelector }} nodeSelector: app: {{ $releaseName }}
能夠看到在 with語句上面增長了一句 {{-$releaseName:=.Release.Name-}},其中 $releaseName就是後面的對象的一個引用變量,它的形式就是 $name,賦值操做使用 :=,這樣 with語句塊內部的 $releaseName變量仍然指向的是 .Release.Name
另外就是咱們在定義一個微服務或者java的項目的時候會設置java的堆內存大小,那麼這個也是比較經常使用的選項,怎麼將這個也加入進去呢,這裏方法不少,可使用toYaml方式,
咱們先去values去定義一下
[root@k8s-master1 one]# tail -4 values.yaml env: - name: JAVA_OPTS value: -Xmx1024m -Xms1014m
經過剛纔方法也是能夠打印的
{{- with .Values.env }} env: {{- toYaml . | nindent 8 }} {{- end }}
八、命名模板
命名模板:使用define定義,template引入,在templates目錄中默認下劃線開頭的文件爲公共模板(helpers.tpl),好比這個yaml裏面有一兩處的都須要這不如toYaml模式,或者if else開關的模式,那麼久可使用這個命名模版了
好比資源的名字都是相同的名字這個就能夠定義一個命名模版,把這一塊的邏輯都寫在一個模版裏,讓這些yaml都引用這一塊,而後他們引用的名字都同樣,好比label這一塊,標籤選擇器,那麼控制器呢須要根據標籤選擇器來匹配pod,那麼這一塊能夠寫到_helper.tpl裏面,這個就是實際存放公共模版的地方,定義模版呢就是使用define定義,template來引入
cat _helpers.tpl {{- define "demo.fullname" -}} {{- .Chart.Name -}}-{{ .Release.Name }} {{- end -}} cat deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ template "demo.fullname" . }} ...
template指令是將一個模板包含在另外一個模板中的方法。可是,template函數不能用於Go模板管道。爲了解決該問題,增長include功能
cat _helpers.tpl {{- define "demo.labels" -}} app: {{ template "demo.fullname" . }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" release: "{{ .Release.Name }}" {{- end -}}
cat deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "demo.fullname" . }} labels: {{- include "demo.labels" . | nindent 4 }} ...
上面包含一個名爲 demo.labels 的模板,而後將值 . 傳遞給模板,最後將該模板的輸出傳遞給 nindent 函數。
3.7 開發本身的Chart:dubbo微服務應用爲例
先建立模板
helm create dubbo
修改Chart.yaml,Values.yaml,
添加經常使用的變量
git clone git@gitee.com:zhaocheng172/helm-dubbo.git