目錄:
根據(jù)微服務(wù)的發(fā)版需求進(jìn)行對(duì)應(yīng)用進(jìn)行調(diào)試,使用chart的模版發(fā)布微服務(wù)
1、基于dubbo微服務(wù)發(fā)布一個(gè)基于生產(chǎn)環(huán)境用到的helm模版
模版地址:git clone git@gitee.com:zhaocheng172/helm-dubbo.git
拉取請(qǐng)把你的公鑰給我,不然拉不下來(lái)
3.6 Chart模板
Helm最核心的就是模板,即模板化的K8S manifests文件。
它本質(zhì)上就是一個(gè)Go的template模板。Helm在Go template模板的基礎(chǔ)上,還會(huì)增加很多東西。如一些自定義的元數(shù)據(jù)信息、擴(kuò)展的庫(kù)以及一些類(lèi)似于編程形式的工作流,例如條件語(yǔ)句、管道等等。這些東西都會(huì)使得我們的模板變得更加豐富。
說(shuō)在前面的話,其實(shí)在helm中,其實(shí)最關(guān)鍵的就是這個(gè)模版的渲染,我們將yaml中可能經(jīng)常變動(dòng)的字段,去指定一個(gè)變量,這個(gè)變量就可以通過(guò)helm的命令行,通過(guò)它的命名行去覆蓋它默認(rèn)的變量,這就能動(dòng)態(tài)的渲染到y(tǒng)aml中,里面最重要的就是這個(gè)模版values,helm幫我們做的事就是集中管理yaml,能動(dòng)態(tài)的渲染這些yaml,因?yàn)樵趯?xiě)yaml時(shí)里面可能會(huì)有很多字段,在后面部署的時(shí)候可能回有其他變化,其實(shí)就是將這些變動(dòng)的字段,動(dòng)態(tài)的批量的去修改,之前沒(méi)有helm的時(shí)候,一般都是也會(huì)設(shè)計(jì)一個(gè)通用的模版來(lái)改變里面經(jīng)常變動(dòng)的字段,一般就是使用sed來(lái)替換里面的值,比如替換鏡像,將鏡像替換一個(gè)名字就可以部署一個(gè)新的應(yīng)用了,替換成功,apply一下就應(yīng)用上了,當(dāng)然這個(gè)鏡像是你提前將代碼編譯好的,然后通過(guò)dockerfile制作一個(gè)自己的鏡像,一般替換的鏡像地址也是harbor上的鏡像地址為準(zhǔn),這樣的話,可能會(huì)寫(xiě)很多替換的命令,顯然也不是很靈活,文件越來(lái)越多,對(duì)管理也是有一定成本,其實(shí)最好的方式有沒(méi)有在一個(gè)文件中,把這些變量字段寫(xiě)進(jìn)去,所有的yaml都可以讀到這個(gè)變量,把它引用到渲染的文件中,這也是helm要做的事,這也是helm核心的功能。
1、模板
有了模板,我們?cè)趺窗盐覀兊呐渲萌谌脒M(jìn)去呢?用的就是這個(gè)values文件。這兩部分內(nèi)容其實(shí)就是chart的核心功能。
當(dāng)我們?nèi)ゲ渴鹨粋€(gè)應(yīng)用的時(shí)候,比如發(fā)布一個(gè)微服務(wù),都是要做這么一個(gè)chart,這個(gè)chart可以來(lái)自于互聯(lián)網(wǎng)上,或者別人分享給你,或者自己制作的都可以,在這個(gè)chart中最核心的就是這個(gè)模版了,我們?nèi)ゲ渴鹨粋€(gè)應(yīng)用,它這個(gè)模版本身就是一個(gè)go的模版,用go去渲染的,只不過(guò)helm在go的基礎(chǔ)之上添寫(xiě)了一些東西,讓它更靈活,比如條件判段
接下來(lái),部署nginx應(yīng)用,熟悉模板使用,先把templates 目錄下面所有文件全部刪除掉,這里我們自己來(lái)創(chuàng)建模板文件,語(yǔ)法的控制,都是滿(mǎn)足這個(gè)模版更多的需求。
比如先創(chuàng)建一個(gè)chart,一共4個(gè)目錄,在templates里面就是我們部署一個(gè)應(yīng)用所需的配置yaml,像deployment,service,ingress等,我們將一些經(jīng)常變動(dòng)的字段寫(xiě)成變量的模式,通過(guò)values去定義這些變量的值,通過(guò)helm install創(chuàng)建的時(shí)候,它就會(huì)進(jìn)行對(duì)values進(jìn)行渲染到我們的template里面了,還有一個(gè)_helpers.tpl,它會(huì)放一些deployment,service都會(huì)用到的模版,比如都會(huì)用到一些通用的字段,那么久可以把它放到_helpers.tpl命名模版里面,NOTES.txt是部署一個(gè)應(yīng)用用到的一個(gè)提示,比如訪問(wèn)的地址,還有一個(gè)test的這個(gè)目錄,比如你部署好一個(gè)應(yīng)用,測(cè)試一下看看是不是部署正常。
[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
先準(zhǔn)備兩個(gè)yaml,然后我們進(jìn)行去對(duì)一些經(jīng)常變的字段,進(jìn)行渲染
[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
然后我們將我們的服務(wù)先發(fā)布出去測(cè)試一下,順便測(cè)試能不能正常訪問(wèn)
我們正常是通過(guò)apply -f 去發(fā)布這樣的一個(gè)服務(wù),現(xiàn)在使用helm來(lái)發(fā)布試一下,其實(shí)效果是一樣的,但是這樣去發(fā)布的話,我們跟apply -f 沒(méi)什么效果了,而helm的核心應(yīng)用的功能在于我們能夠有效的去渲染我們的變量,使發(fā)布我們的微服務(wù)更靈活,比如就可以通過(guò)模版進(jìn)行變量的渲染修改一下鏡像的地址,發(fā)布服務(wù)的名稱(chēng),以及副本數(shù),等等,來(lái)動(dòng)態(tài)的傳入,快速發(fā)布多套微服務(wù),簡(jiǎn)單說(shuō)就是部署一套通用的模版,來(lái)部署一些常規(guī)性的應(yīng)用。
[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
也就是部署一個(gè)chart,使用這個(gè)模版,能夠部署一些常規(guī)性的應(yīng)用,首先需要經(jīng)常變動(dòng)的是名字,還有副本,以及鏡像名稱(chēng)
2、調(diào)試
Helm也提供了--dry-run 調(diào)試參數(shù),幫助你驗(yàn)證模板正確性。在執(zhí)行helm install時(shí)候帶上這兩個(gè)參數(shù)就可以把對(duì)應(yīng)的values值和渲染的資源清單打印出來(lái),而不會(huì)真正的去部署一個(gè)release。
比如我們來(lái)調(diào)試上面創(chuàng)建的 chart 包:helm install pod-nodejs-tools --dry-run /root/one
3、內(nèi)置對(duì)象
{{ Release.Name}}這個(gè)屬于內(nèi)置變量,這個(gè)內(nèi)置變量其實(shí)就是我們install的時(shí)候進(jìn)行對(duì)我們部署應(yīng)用起的名字,也就是傳進(jìn)來(lái)了,那么就可以直接使用這個(gè)來(lái)部署資源的名字
{{ Chart.Name}}這個(gè)值也是屬于helm的一個(gè)內(nèi)置變量,這個(gè)也就是我們創(chuàng)建chart后模版有Chart.yaml這個(gè)yaml,其實(shí)這個(gè)就是在這里面去取的值,當(dāng)然項(xiàng)目的名字,一般都是統(tǒng)一的,可以直接通過(guò){{ Values.name}}我們自己去定義,也就是在values.yaml這個(gè)里面去定義的
我們編寫(xiě)好了變量的傳輸之后,也可以輸出一下,看看是不是能夠正常輸出渲染
這里的pod-base-common其實(shí)就會(huì)使我在{{ Release.name}}去生效 --dry-run就是預(yù)執(zhí)行 ,one就是我的chart的目錄
像一些常用的release內(nèi)置變量,Chart的變量可以直接在chart包中去看到
[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 }}
4、Values自定義變量
Values對(duì)象是為Chart模板提供值,這個(gè)對(duì)象的值有4個(gè)來(lái)源:
chart 包中的 values.yaml 文件
父 chart 包的 values.yaml 文件
通過(guò) helm install 或者 helm upgrade 的 -f或者 --values參數(shù)傳入的自定義的 yaml 文件
通過(guò) --set 參數(shù)傳入的值[root@k8s-master1 one]# helm install pod-mapper-service --set replicas=1 ../one/
通過(guò)--set命令會(huì)優(yōu)先將覆蓋values的值,創(chuàng)建一個(gè)副本,而不是二個(gè)了。
chart 的 values.yaml 提供的值可以被用戶(hù)提供的 values 文件覆蓋,而該文件同樣可以被 --set提供的參數(shù)所覆蓋。
[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
執(zhí)行之后查看渲染后的結(jié)果使用get manifest+項(xiàng)目的名稱(chēng),通過(guò)helm ls,就能查看到helm創(chuàng)建的服務(wù)
[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
比如我們?cè)贉y(cè)試一下,比如我們的代碼更新了,通過(guò)dockerfile又構(gòu)成新的鏡像了,那么我們需要去替換新的鏡像,怎么做?
其實(shí)講我們的values下定義的名稱(chēng)換成新的鏡像的地址就可以了,這里做演示寫(xiě)的是nginx1.17
然后通過(guò)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
通過(guò)get manifest可以查看到渲染后的鏡像的地址,一般在微服務(wù)的發(fā)布當(dāng)中為了保證項(xiàng)目名字的一致性,都是統(tǒng)一使用{{Values.name}},自己設(shè)置變量[root@k8s-master1 one]# helm get manifest pod-css-commons
比如現(xiàn)在有要發(fā)布一個(gè)微服務(wù)
那么我們一般替換的一般就是服務(wù)的名字還有鏡像了
直接在values中去修改成新的鏡像的地址還有項(xiàng)目的名字就--dry-run 一下測(cè)試沒(méi)問(wèn)題直接發(fā)布
[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
5、管道與函數(shù)
剛才的values,以及內(nèi)置的對(duì)象其實(shí)就是將值傳給模板引擎進(jìn)行渲染,另外模板引擎還支持對(duì)拿到數(shù)據(jù)進(jìn)行二次處理,也就是一定非要使用values的值,也可以對(duì)這個(gè)模版進(jìn)行二次處理,比如我將拿到的數(shù)據(jù),第一個(gè)字母為大寫(xiě),或者我將拿到的值的字符串進(jìn)行加個(gè)雙引號(hào),那么都可以對(duì)這個(gè)模版引擎進(jìn)行二次處理,比如將拿到的值變成一個(gè)字符串,那么這就用到了一個(gè)函數(shù),那么這個(gè)模版引擎支持這個(gè)函數(shù),那么這個(gè)函數(shù)不是特別的常用,但是也會(huì)用到這個(gè),比如deployment這里,比如labels這里拿到這個(gè)值并加個(gè)雙引號(hào),有的yaml的值必須加雙引號(hào)才可以,其實(shí)這個(gè)實(shí)現(xiàn)的話也比較簡(jiǎn)單,直接加一個(gè)quote就可以
雙引號(hào)
labels:
app: {{ quote .Values.name }}
測(cè)試效果已經(jīng)給將雙引號(hào)給添加上了,其實(shí)這就是quote函數(shù)幫我們做的一個(gè)二次處理,當(dāng)我們特定的給一些值加雙引號(hào)的時(shí)候,就可以直接通過(guò)quote函數(shù)來(lái)實(shí)現(xiàn)
[root@k8s-master1 one]# helm install pod-tools-service --dry-run ../one/
labels:
app: "pod-mapper-service"
再比如將一個(gè)特定的變量直接傳入,不通過(guò)values,我定義的env這個(gè)字段,默認(rèn)是沒(méi)有的,通過(guò){{ default "xxxx" .Values.env }} 傳入,比如這就是一個(gè)默認(rèn)值,不需要變的,就可以直接這么定義
spec:
nodeSelector:
team: {{ .Values.team }}
env: {{ default "JAVA_OPTS" .Values.env }}
那么如果values里面有這個(gè)值,它默認(rèn)就會(huì)使用values里面的值,如果沒(méi)有就會(huì)使用default使用默認(rèn)的值
像縮進(jìn)這一塊,本身yaml就是以層級(jí)關(guān)系來(lái)定義的,那么有時(shí)候我們就會(huì)用到這種的需求來(lái)渲染我們的層級(jí)關(guān)系
其他函數(shù):
縮進(jìn):{{ .Values.resources | indent 12 }}
大寫(xiě):{{ upper .Values.resources }}
首字母大寫(xiě):{{ title .Values.resources }}
6、流程控制
流程控制是為模板提供了一種能力,滿(mǎn)足更復(fù)雜的數(shù)據(jù)邏輯處理。
Helm模板語(yǔ)言提供以下流程控制語(yǔ)句:
if/else 條件塊
with 指定范圍
range 循環(huán)塊
像縮進(jìn)流程控制一般也都會(huì)用到,像else/if了都會(huì)做一下復(fù)雜邏輯的處理,
values下定義這個(gè)參數(shù)
test: "123"
templates/deployment.yaml下去定義這個(gè)判斷,if test=123,那么就輸出test:a,否則如果變量的值為其他,這里就打印test:b了,這種的應(yīng)用的場(chǎng)景也能根據(jù)自己的實(shí)際應(yīng)用場(chǎng)景對(duì)yaml進(jìn)行定義,但是這種遇到的情況也不多。
spec:
nodeSelector:
team: {{ .Values.team }}
env: {{ default "JAVA_OPTS" .Values.env }}
{{ if eq .Values.test "123" }}
test: a
{{ else }}
test: b
{{ end }}
其實(shí)在這里輸出的話,給留出空格,其實(shí)就是剛才的{{我們定義的參數(shù)留下的}},這個(gè)直接去掉就可以了,通過(guò)-就可以刪除
eq運(yùn)算符判斷是否相等,另外還支持ne、 lt、 gt、 and、 or等運(yùn)算符。
{{- if eq .Values.test "123" }}
test: a
{{- else }}
test: b
{{- end }}
containers:
條件判斷就是判斷條件是否為真,如果值為以下幾種情況則為false:
一個(gè)布爾類(lèi)型的 為flase
一個(gè)數(shù)字 零
一個(gè) 空的字符串
一個(gè) nil(空或 null)
一個(gè)空的集合( map、 slice、 tuple、 dict、 array)
除了上面的這些情況外,其他所有條件都為 真。
比如values的值設(shè)置的就是flase,那就不為真
或者就是values的值設(shè)置的就是0,那么默認(rèn)也是設(shè)置為false,那也不為真
如果為空,那么也為false,或者為集合,以上的情況都為false
那么我們?cè)趘alues設(shè)置一個(gè)0,測(cè)試一下,然后這邊打印的為b,說(shuō)明就是假的
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
現(xiàn)在我們使用它們helm官方原來(lái)的values的模版來(lái)創(chuàng)建一個(gè)應(yīng)用而且它這個(gè)支持序列化的格式化的結(jié)構(gòu),比如鏡像image,可能會(huì)有他的鏡像的地址標(biāo)簽名字,可能下面還定義多個(gè)屬性,所以這種就可以定義這種結(jié)構(gòu)化的一個(gè)格式,比如像倉(cāng)庫(kù)的地址,拉取鏡像的策略
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
現(xiàn)在再增加一個(gè)資源限制
做一個(gè)判斷當(dāng)默認(rèn)為false或者true的情況下,做相關(guān)的動(dòng)作,就是說(shuō)資源限制用不用,如果定義的為false,那么就不使用這里面的資源,那么為ture的話,就使用,或者不設(shè)置,將限制的資源注釋去掉
現(xiàn)在就去判斷這個(gè)resource是不是為真,如果為真的話就使用resource,然后對(duì)這個(gè)pod多一個(gè)資源的限制,如果為假的話,就不做資源限制,直接判斷{{ if .Values.resources }}
這里我先判斷為真測(cè)試一下,它會(huì)將我們的判斷為真的加進(jìn)去
[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 }}
這里就會(huì)去引用我們下面的變量,如果沒(méi)這個(gè)需求就可以直接在resources: 0 ,或者""或者false都可以,然后將下面的注釋就不會(huì)引用了,也就是相當(dāng)于一個(gè)開(kāi)關(guān),很好的去管理我們的應(yīng)用
[root@k8s-master1 one]# cat values.yaml
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
測(cè)試結(jié)果查看
[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就是關(guān)閉的意思,執(zhí)行之后首先會(huì)根據(jù)enabeld去使用
resources:
enabled: false
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
那么在{{ if .Values.resource.enabled}} 去定義將values的開(kāi)關(guān)為true就就會(huì)使用,為false就不會(huì)使用
[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 }}
像這樣的需求也很多,有的微服務(wù)不需要去創(chuàng)建ingress的,有的可能需要,或者有的可能不使用ingress作為集群外部的負(fù)載均衡器流入到集群內(nèi)部的你的服務(wù)上,直接使用service的clusterIP再部署幾臺(tái)nginx負(fù)載均衡器來(lái)進(jìn)行負(fù)責(zé)轉(zhuǎn)發(fā)內(nèi)部的服務(wù),通過(guò)slb進(jìn)行暴露出去,那么我們?nèi)?shí)現(xiàn)一下這兩個(gè)需求
在values中它有這個(gè)模版enabled可以跟剛才的也一樣,如果設(shè)置為false的話就不創(chuàng)建ingress規(guī)則,如果為true的話就創(chuàng)建這個(gè)規(guī)則
先對(duì)service進(jìn)行定義,也就是流程控制,現(xiàn)在對(duì)service不進(jìn)行使用
values進(jìn)行設(shè)置開(kāi)關(guān)為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 }}
執(zhí)行之后不會(huì)創(chuàng)建service,因?yàn)槲以O(shè)置的if去判斷為假的話,那么就不創(chuàng)建service,并設(shè)置的開(kāi)關(guān)為false,那么設(shè)置為true就直接可以創(chuàng)建service了[root@k8s-master1 templates]# helm install pod-base-tools --dry-run ../../one/
現(xiàn)在創(chuàng)建一個(gè)ingress,也設(shè)置一個(gè)開(kāi)關(guān),其實(shí)方法也是一樣的
[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}}其中的 .就是表示對(duì)當(dāng)前范圍的引用, .Values就是告訴模板在當(dāng)前范圍中查找 Values對(duì)象的值。而 with語(yǔ)句就可以來(lái)控制變量的作用域范圍,其語(yǔ)法和一個(gè)簡(jiǎn)單的 if語(yǔ)句比較類(lèi)似
一個(gè)小問(wèn)題就是當(dāng)我們?nèi)?xiě)變量引用的時(shí)候都會(huì)在前面加一個(gè).這個(gè)點(diǎn)的意思就是從哪個(gè)范圍去找,按照.的話,就是按這個(gè)生成模版的結(jié)構(gòu)去找的
再使用一下nodeSelector這個(gè)值吧,這個(gè)看實(shí)際的場(chǎng)景,一般呢都是會(huì)設(shè)置調(diào)度的節(jié)點(diǎn)進(jìn)行分組,這樣才保證我們更好的去管理node節(jié)點(diǎn)的分布微服務(wù)的布局
這個(gè)呢也可以使用之前的語(yǔ)法if去做判斷
也可以通過(guò)這個(gè)開(kāi)關(guān)的方式進(jìn)行配置,或者就是with的方式,或者就是toyaml的函數(shù)方式
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 }}
或者把開(kāi)關(guān)去掉,用with直接去讀取我們的參數(shù)也是可以的
[root@k8s-master1 one]# tail -4 values.yaml
nodeSelector:
team: team2
在deployment去定義這個(gè)字段,- with 指定.team,來(lái)讀取相應(yīng)的值
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
team: {{ .team }}
{{- else }}
{{- end }}
使用toYaml方式
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
with是一個(gè)循環(huán)構(gòu)造。使用.Values.nodeSelector中的值:將其轉(zhuǎn)換為Yaml。
toYaml之后的點(diǎn)是循環(huán)中.Values.nodeSelector的當(dāng)前值
range
在 Helm 模板語(yǔ)言中,使用 range關(guān)鍵字來(lái)進(jìn)行循環(huán)操作。
我們?cè)?values.yaml文件中添加上一個(gè)變量列表:
像range一般要寫(xiě)多個(gè)元素的時(shí)候要使用,像toyaml和with一般用于結(jié)構(gòu)化的層次比較多的,比較使用env這樣的適合使用range,
cat values.yaml
test:
- 1
- 2
- 3
循環(huán)打印該列表:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
test: |
{{- range .Values.test }}
{{ . }}
{{- end }}
循環(huán)內(nèi)部我們使用的是一個(gè) .,這是因?yàn)楫?dāng)前的作用域就在當(dāng)前循環(huán)內(nèi),這個(gè) .引用的當(dāng)前讀取的元素
7、變量
變量,在模板中,使用變量的場(chǎng)合不多,但我們將看到如何使用它來(lái)簡(jiǎn)化代碼,并更好地利用with和range。因?yàn)閯偛盼覀冇玫降膚ith,不能在下面再去定義其他的變量了,那么怎么在with中去引用一些全值內(nèi)置的變量呢,有兩種方法,一個(gè)是使用helm的變量賦值進(jìn)行去使用,第二種是使用$去使用
測(cè)試一下,先不添加$
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
app: {{ .Values.name }}
執(zhí)行結(jié)果是這樣的
[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
那么加上$的話這樣就會(huì)正常輸出
spec:
nodeSelector:
app: pod-base-user
team: team2
也可以使用另外一種形式來(lái)輸出
spec:
{{- $releaseName := .Release.Name -}}
{{- with .Values.nodeSelector }}
nodeSelector:
app: {{ $releaseName }}
可以看到在 with語(yǔ)句上面增加了一句 {{-$releaseName:=.Release.Name-}},其中 $releaseName就是后面的對(duì)象的一個(gè)引用變量,它的形式就是 $name,賦值操作使用 :=,這樣 with語(yǔ)句塊內(nèi)部的 $releaseName變量仍然指向的是 .Release.Name
另外就是我們?cè)诙x一個(gè)微服務(wù)或者java的項(xiàng)目的時(shí)候會(huì)設(shè)置java的堆內(nèi)存大小,那么這個(gè)也是比較常用的選項(xiàng),怎么將這個(gè)也加入進(jìn)去呢,這里方法很多,可以使用toYaml方式,
我們先去values去定義一下
[root@k8s-master1 one]# tail -4 values.yaml
env:
- name: JAVA_OPTS
value: -Xmx1024m -Xms1014m
通過(guò)剛才方法也是可以打印的
{{- with .Values.env }}
env:
{{- toYaml . | nindent 8 }}
{{- end }}
8、命名模板
命名模板:使用define定義,template引入,在templates目錄中默認(rèn)下劃線開(kāi)頭的文件為公共模板(helpers.tpl),比如這個(gè)yaml里面有一兩處的都需要這不如toYaml模式,或者if else開(kāi)關(guān)的模式,那么久可以使用這個(gè)命名模版了
比如資源的名字都是相同的名字這個(gè)就可以定義一個(gè)命名模版,把這一塊的邏輯都寫(xiě)在一個(gè)模版里,讓這些yaml都引用這一塊,然后他們引用的名字都一樣,比如label這一塊,標(biāo)簽選擇器,那么控制器呢需要根據(jù)標(biāo)簽選擇器來(lái)匹配pod,那么這一塊可以寫(xiě)到_helper.tpl里面,這個(gè)就是實(shí)際存放公共模版的地方,定義模版呢就是使用define定義,template來(lái)引入
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指令是將一個(gè)模板包含在另一個(gè)模板中的方法。但是,template函數(shù)不能用于Go模板管道。為了解決該問(wèn)題,增加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 }}
...
上面包含一個(gè)名為 demo.labels 的模板,然后將值 . 傳遞給模板,最后將該模板的輸出傳遞給 nindent 函數(shù)。
3.7 開(kāi)發(fā)自己的Chart:dubbo微服務(wù)應(yīng)用為例
先創(chuàng)建模板
helm create dubbo
修改Chart.yaml,Values.yaml,
添加常用的變量
git clone git@gitee.com:zhaocheng172/helm-dubbo.git
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。
網(wǎng)頁(yè)標(biāo)題:K8s原生微服務(wù)管理工具h(yuǎn)elm-v3的使用初探實(shí)踐(2)-創(chuàng)新互聯(lián)
鏈接分享:http://jinyejixie.com/article14/dchsde.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營(yíng)銷(xiāo)型網(wǎng)站建設(shè)、做網(wǎng)站、定制開(kāi)發(fā)、商城網(wǎng)站、響應(yīng)式網(wǎng)站、小程序開(kāi)發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容