一、使用Replication Controller(RC)、Replica Set(RS) 管理Pod
如果有一種工具能夠來幫助我們管理Pod就好了,Pod不夠了自動幫我新增一個,Pod掛了自動幫我在合適的節(jié)點上重新啟動一個Pod,這樣是不是遇到上面的問題我們都不需要手動去解決了。
幸運的是,Kubernetes就為我們提供了這樣的資源對象:
- Replication Controller:用來部署、升級Pod
- Replica Set:下一代的Replication Controller
- Deployment:可以更加方便的管理Pod和Replica Set
1 Replication Controller(RC)
Replication Controller簡稱RC,RC是Kubernetes系統(tǒng)中的核心概念之一,簡單來說,RC可以保證在任意時間運行Pod的副本數(shù)量,能夠保證Pod總是可用的。如果實際Pod數(shù)量比指定的多那就結束掉多余的,如果實際數(shù)量比指定的少就新啟動一些Pod,當Pod失敗、被刪除或者掛掉后,RC都會去自動創(chuàng)建新的Pod來保證副本數(shù)量,所以即使只有一個Pod,我們也應該使用RC來管理我們的Pod。
運行Pod的節(jié)點掛了,RC檢測到Pod失敗了,就會去合適的節(jié)點重新啟動一個Pod就行,不需要我們手動去新建一個Pod了。如果是第一種情況的話在活動開始之前我們給Pod指定10個副本,結束后將副本數(shù)量改成2,這樣是不是也遠比我們手動去啟動、手動去關閉要好得多,而且我們后面還會給大家介紹另外一種資源對象HPA可以根據(jù)資源的使用情況來進行自動擴縮容。
現(xiàn)在我們來使用RC來管理我們前面使用的Nginx的Pod,YAML文件如下:
apiVersion: v1
kind: ReplicationController
metadata:
name: rc-demo
labels:
name: rc
spec:
replicas: 3
selector:
name: rc
template:
metadata:
labels:
name: rc
spec:
containers:
- name: nginx-demo
image: nginx
ports:
- containerPort: 80
上面的YAML文件相對于我們之前的Pod的格式:
- kind:ReplicationController
- spec.replicas: 指定Pod副本數(shù)量,默認為1
- spec.selector: RC通過該屬性來篩選要控制的Pod
- spec.template: 這里就是我們之前的Pod的定義的模塊,但是不需要apiVersion和kind了
- spec.template.metadata.labels: 注意這里的Pod的labels要和spec.selector相同,這樣RC就可以來控制當前這個Pod了。
這個YAML文件中的意思就是定義了一個RC資源對象,它的名字叫rc-demo,保證一直會有3個Pod運行,Pod的鏡像是nginx鏡像。
注意spec.selector和spec.template.metadata.labels這兩個字段必須相同,否則會創(chuàng)建失敗的,當然我們也可以不寫spec.selector,這樣就默認與Pod模板中的metadata.labels相同了。所以為了避免不必要的錯誤的話,不寫為好。
然后我們來創(chuàng)建上面的RC對象(保存為 rc-demo.yaml):
$ kubectl create -f rc-demo.yaml
查看RC:
$ kubectl get rc
查看具體信息:
$ kubectl describe rc rc-demo
然后我們通過RC來修改下Pod的副本數(shù)量為2:
$ kubectl apply -f rc-demo.yaml
或者
$ kubectl edit rc rc-demo
而且我們還可以用RC來進行滾動升級,比如我們將鏡像地址更改為nginx:1.7.9:
$ kubectl rolling-update rc-demo --image=nginx:1.7.9
但是如果我們的Pod中多個容器的話,就需要通過修改YAML文件來進行修改了:
$ kubectl rolling-update rc-demo -f rc-demo.yaml
RC無法進行回滾操作
- 如果升級完成后出現(xiàn)了新的問題,想要一鍵回滾到上一個版本的話,使用RC只能用同樣的方法把鏡像地址替換成之前的,然后重新滾動升級。
2 Replication Set(RS)
Replication Set簡稱RS,隨著Kubernetes的高速發(fā)展,官方已經(jīng)推薦我們使用RS和Deployment來代替RC了,實際上RS和RC的功能基本一致,目前唯一的一個區(qū)別就是RC只支持基于等式的selector(env=dev或environment!=qa),但RS還支持基于集合的selector(version in (v1.0, v2.0)),這對復雜的運維管理就非常方便了。
eg:
apiVersion: v1
kind: ReplicationSet
metadata:
name: rc-demo
labels:
name: rc
spec:
replicas: 3
selector:
name: rc
template:
metadata:
labels:
name: rc
spec:
containers:
- name: nginx-demo
image: nginx
ports:
- containerPort: 80
kubectl命令行工具中關于RC的大部分命令同樣適用于我們的RS資源對象。不過我們也很少會去單獨使用RS,它主要被Deployment這個更加高層的資源對象使用,除非用戶需要自定義升級功能或根本不需要升級Pod,在一般情況下,我們推薦使用Deployment而不直接使用Replica Set。
最后我們總結下關于RC/RS的一些特性和作用吧:
- 大部分情況下,我們可以通過定義一個RC實現(xiàn)的Pod的創(chuàng)建和副本數(shù)量的控制
- RC中包含一個完整的Pod定義模塊(不包含apiversion和kind)
- RC是通過label selector機制來實現(xiàn)對Pod副本的控制的
- 通過改變RC里面的Pod副本數(shù)量,可以實現(xiàn)Pod的擴縮容功能
- 通過改變RC里面的Pod模板中鏡像版本,可以實現(xiàn)Pod的滾動升級功能(但是不支持一鍵回滾,需要用相同的方法去修改鏡像地址)
二、Deployment的使用
首先RC是Kubernetes的一個核心概念,當我們把應用部署到集群之后,需要保證應用能夠持續(xù)穩(wěn)定的運行,RC就是這個保證的關鍵,主要功能如下:
- 確保Pod數(shù)量:它會確保Kubernetes中有指定數(shù)量的Pod在運行,如果少于指定數(shù)量的Pod,RC就會創(chuàng)建新的,反之這會刪除多余的,保證Pod的副本數(shù)量不變。
- 確保Pod健康:當Pod不健康,比如運行出錯了,總之無法提供正常服務時,RC也會殺死不健康的Pod,重新創(chuàng)建新的。
- 彈性伸縮:在業(yè)務高峰或者低峰的時候,可以用過RC來動態(tài)的調(diào)整Pod數(shù)量來提供資源的利用率,當然我們也提到過如果使用HPA這種資源對象的話可以做到自動伸縮。
- 滾動升級:滾動升級是一種平滑的升級方式,通過逐步替換的策略,保證整體系統(tǒng)的穩(wěn)定性,
Deployment同樣也是Kubernetes系統(tǒng)的一個核心概念,主要職責和RC一樣的都是保證Pod的數(shù)量和健康,二者大部分功能都是完全一致的,我們可以看成是一個升級版的RC控制器,那Deployment又具備那些新特性呢?
- RC的全部功能:Deployment具備上面描述的RC的全部功能
- 事件和狀態(tài)查看:可以查看Deployment的升級詳細進度和狀態(tài)
- 回滾:當升級Pod的時候如果出現(xiàn)問題,可以使用回滾操作回滾到之前的任一版本
- 版本記錄:每一次對Deployment的操作,都能夠保存下來,這也是保證可以回滾到任一版本的基礎
- 暫停和啟動:對于每一次升級都能夠隨時暫停和啟動
作為對比,我們知道Deployment作為新一代的RC,不僅在功能上更為豐富了,同時我們也說過現(xiàn)在官方也都是推薦使用Deployment來管理Pod的,比如一些官方組件kube-dns、kube-proxy也都是使用的Deployment來管理的,所以當大家在使用的使用也最好使用Deployment來管理Pod。
1 創(chuàng)建
可以看出一個Deployment擁有多個Replica Set,而一個Replica Set擁有一個或多個Pod。
一個Deployment控制多個rs主要是為了支持回滾機制,每當Deployment操作時,Kubernetes會重新生成一個Replica Set并保留,以后有需要的話就可以回滾至之前的狀態(tài)。
下面創(chuàng)建一個Deployment,它創(chuàng)建了一個Replica Set來啟動3個nginx pod,yaml文件如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
k8s-app: nginx-demo
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
將上面內(nèi)容保存為: nginx-deployment.yaml,執(zhí)行命令:
$ kubectl create -f nginx-deployment.yaml
deployment "nginx-deploy" created
然后執(zhí)行一下命令查看剛剛創(chuàng)建的Deployment:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deploy 3 0 0 0 1s
隔一會再次執(zhí)行上面命令:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deploy 3 3 3 3 4m
我們可以看到Deployment已經(jīng)創(chuàng)建了1個Replica Set了,執(zhí)行下面的命令查看rs和pod:
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-431080787 3 3 3 6m
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deploy-431080787-53z8q 1/1 Running 0 7m app=nginx,pod-template-hash=431080787
nginx-deploy-431080787-bhhq0 1/1 Running 0 7m app=nginx,pod-template-hash=431080787
nginx-deploy-431080787-sr44p 1/1 Running 0 7m app=nginx,pod-template-hash=431080787
上面的Deployment的yaml文件中的replicas:3將會保證我們始終有3個POD在運行。
2 滾動升級
現(xiàn)在我們將剛剛保存的yaml文件中的nginx鏡像修改為nginx:1.13.3,然后在spec下面添加滾動升級策略:
minReadySeconds: 5
strategy:
# indicate which strategy we want for rolling update
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
minReadySeconds:
Kubernetes在等待設置的時間后才進行升級
- 如果沒有設置該值,Kubernetes會假設該容器啟動起來后就提供服務了
- 如果沒有設置該值,在某些極端情況下可能會造成服務不正常運行
maxSurge:
- 升級過程中最多可以比原先設置多出的POD數(shù)量
- 例如:maxSurage=1,replicas=5,則表示Kubernetes會先啟動1一個新的Pod后才刪掉一個舊的POD,整個升級過程中最多會有5+1個POD。
maxUnavaible:
- 升級過程中最多有多少個POD處于無法提供服務的狀態(tài)
- 當maxSurge不為0時,該值也不能為0
- 例如:maxUnavaible=1,則表示Kubernetes整個升級過程中最多會有1個POD處于無法服務的狀態(tài)。
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
namespace: test
labels:
app: nginx-demo
spec:
replicas: 3
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.13.3
ports:
- containerPort: 80
name: nginxweb
然后執(zhí)行命令:
$ kubectl apply -f nginx-deployment.yaml --record=true
deployment "nginx-deploy" configured
然后我們可以使用rollout命令:
查看狀態(tài):kubectl rollout status deployment nginx-deploy
$ kubectl rollout status deployment/nginx-deploy
Waiting for rollout to finish: 1 out of 3 new replicas have been updated..
deployment "nginx-deploy" successfully rolled out
暫停升級
$ kubectl rollout pause deployment nginx-deploy
繼續(xù)升級
$ kubectl rollout resume deployment nginx-deploy
升級結束后,繼續(xù)查看rs的狀態(tài):
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-2078889897 0 0 0 47m
nginx-deploy-3297445372 3 3 3 42m
nginx-deploy-431080787 0 0 0 1h
根據(jù)AGE我們可以看到離我們最近的當前狀態(tài)是:3,和我們的yaml文件是一致的,證明升級成功了。
用describe命令可以查看升級的全部信息:
kubectl describe deployment nginx-deploy
Name: nginx-deploy
Namespace: default
CreationTimestamp: Wed, 18 Oct 2017 16:58:52 +0800
Labels: k8s-app=nginx-demo
Annotations: deployment.kubernetes.io/revision=3
kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"labels":{"k8s-app":"nginx-demo"},"name":"nginx-deploy","namespace":"defa...
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.13.3
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Progressing True NewReplicaSetAvailable
Available True MinimumReplicasAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deploy-3297445372 (3/3 replicas created)
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
50m 50m 1 deployment-controller Normal ScalingReplicaSet Scaled up replica set nginx-deploy-2078889897 to 1
45m 45m 1 deployment-controller Normal ScalingReplicaSet Scaled down replica set nginx-deploy-2078889897 to 0
45m 45m 1 deployment-controller Normal ScalingReplicaSet Scaled up replica set nginx-deploy-3297445372 to 1
39m 39m 1 deployment-controller Normal ScalingReplicaSet Scaled down replica set nginx-deploy-431080787 to 2
39m 39m 1 deployment-controller Normal ScalingReplicaSet Scaled up replica set nginx-deploy-3297445372 to 2
38m 38m 1 deployment-controller Normal ScalingReplicaSet Scaled down replica set nginx-deploy-431080787 to 1
38m 38m 1 deployment-controller Normal ScalingReplicaSet Scaled up replica set nginx-deploy-3297445372 to 3
38m 38m 1 deployment-controller Normal ScalingReplicaSet Scaled down replica set nginx-deploy-431080787 to 0
3 回滾Deployment
我們已經(jīng)能夠滾動平滑的升級我們的Deployment了,但是如果升級后的POD出了問題該怎么辦?我們能夠想到的最好最快的方式當然是回退到上一次能夠提供正常工作的版本,Deployment就為我們提供了回滾機制。
首先,查看Deployment的升級歷史:
$ kubectl rollout history deployment nginx-deploy
deployments "nginx-deploy"
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 kubectl apply --filename=Desktop/nginx-deployment.yaml --record=true
從上面的結果可以看出在執(zhí)行Deployment升級的時候最好帶上record參數(shù),便于我們查看歷史版本信息。
默認情況下,所有通過kubectl xxxx --record都會被kubernetes記錄到etcd進行持久化,這無疑會占用資源,最重要的是,時間久了,當你kubectl get rs時,會有成百上千的垃圾RS返回給你,那時你可能就眼花繚亂了。
上生產(chǎn)時,我們最好通過設置Deployment的.spec.revisionHistoryLimit來限制最大保留的revision number,比如15個版本,回滾的時候一般只會回滾到最近的幾個版本就足夠了。
其實rollout history中記錄的revision都和ReplicaSets一一對應。如果手動delete某個ReplicaSet,對應的rollout history就會被刪除,也就是還說你無法回滾到這個revison了。
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
namespace: test
labels:
app: nginx-demo
spec:
replicas: 3
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: nginxweb
rollout history和ReplicaSet的對應關系,可以在kubectl describe rs $RSNAME返回的revision字段中得到,這里的revision就對應著rollout history返回的revison。
同樣我們可以使用下面的命令查看單個revison的信息:
$ kubectl rollout history deployment nginx-deploy --revision=3
deployments "nginx-deploy" with revision #3
Pod Template:
Labels: app=nginx
pod-template-hash=3297445372
Annotations: kubernetes.io/change-cause=kubectl apply --filename=nginx-deployment.yaml --record=true
Containers:
nginx:
Image: nginx:1.13.3
Port: 80/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
假如現(xiàn)在要直接回退到當前版本的前一個版本:
$ kubectl rollout undo deployment nginx-deploy
deployment "nginx-deploy" rolled back
當然也可以用revision回退到指定的版本:
$ kubectl rollout undo deployment nginx-deploy --to-revision=2
deployment "nginx-deploy" rolled back
刪除一個rs
$ kubectl delete rs nginx-deploy-431080787
三、 Pod 自動擴縮容HPA
手工執(zhí)行kubectl scale命令和在Dashboard上操作可以實現(xiàn)Pod的擴縮容,但是這樣畢竟需要每次去手工操作一次,而且指不定什么時候業(yè)務請求量就很大了,所以如果不能做到自動化的去擴縮容的話,這也是一個很麻煩的事情。
Kubernetes為我們提供了這樣一個資源對象:Horizontal Pod Autoscaling(Pod水平自動伸縮),簡稱HPA。HAP通過監(jiān)控分析RC或者Deployment控制的所有Pod的負載變化情況來確定是否需要調(diào)整Pod的副本數(shù)量,這是HPA最基本的原理。
HPA在kubernetes集群中被設計成一個controller
- 我們可以簡單的通過kubectl autoscale命令來創(chuàng)建一個HPA資源對象,
- HPA Controller默認30s輪詢一次(可通過kube-controller-manager的標志–horizontal-pod-autoscaler-sync-period進行設置),查詢指定的資源(RC或者Deployment)中Pod的資源使用率,并且與創(chuàng)建時設定的值和指標做對比,從而實現(xiàn)自動伸縮的功能。
當你創(chuàng)建了HPA后,HPA會從Heapster或者用戶自定義的RESTClient端獲取每一個一個Pod利用率或原始值的平均值,然后和HPA中定義的指標進行對比,同時計算出需要伸縮的具體值并進行相應的操作。目前,HPA可以從兩個地方獲取數(shù)據(jù):
- Heapster:僅支持CPU使用率
- 自定義監(jiān)控:
實際上我們已經(jīng)默認把Heapster(1.4.2 版本)相關的鏡像都已經(jīng)拉取到節(jié)點上了,所以接下來我們只需要部署即可:Heapster的github頁面。
heapster.yaml中的image: gcr.io/google_containers/heapster-amd64:v1.3.0可能需要依據(jù)本地的image tag進行修改。
grafana.yaml(類似dashboard)中的image: gcr.io/google_containers/heapster-grafana-amd64:v4.2.0可能需要依據(jù)本地的image tag進行修改。
我們將該目錄下面的yaml文件保存到我們的集群上,然后使用kubectl命令行工具創(chuàng)建即可.
執(zhí)行所有的yaml文件
kubectl create -f .
查看某個pod的運行日志:
kubectl logs -f heapster-676cc864c6 -n kube-system
通過yaml文件刪除pod
kubectl delete -f heapster.yaml
問題:直接啟動heapster會出現(xiàn)以下問題:heapster沒有權限
需要將heapster綁定到cluster-admin
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: heapster
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: heapster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: heapster
namespace: kube-system
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: heapster
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
task: monitoring
k8s-app: heapster
spec:
serviceAccountName: heapster
containers:
- name: heapster
image: gcr.io/google_containers/heapster-amd64:v1.3.0
imagePullPolicy: IfNotPresent
command:
- /heapster
- --source=kubernetes:https://kubernetes.default
- --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086
---
apiVersion: v1
kind: Service
metadata:
labels:
task: monitoring
# For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons)
# If you are NOT using this as an addon, you should comment out this line.
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: Heapster
name: heapster
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 8082
selector:
k8s-app: heapster
重新kubectl delete yaml、kubectl reate即可
另外創(chuàng)建完成后,如果需要在Dashboard當中看到監(jiān)控圖表,我們還需要在Dashboard中配置上我們的heapster-host。
為了能夠創(chuàng)建HPA,可能需要修改master上的kube-controller-manager.yaml
需要在command中增加下面的命令(修改完畢,則自動更新):
1 使用kubectl autoscale
我們來創(chuàng)建一個Deployment管理的Nginx Pod,然后利用HPA來進行自動擴縮容。
定義Deployment的YAML文件如下:(hap-deploy-demo.yaml)
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: hpa-demo
labels:
app: hpa
spec:
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: 100m
ports:
- containerPort: 80
然后創(chuàng)建Deployment
$ kubectl create -f hpa-deploy-demo.yaml
現(xiàn)在我們來創(chuàng)建一個HPA,可以使用kubectl autoscale命令來創(chuàng)建:
$ kubectl autoscale deployment hpa-nginx-deploy --cpu-percent=10 --min=1 --max=10
deployment "hpa-nginx-deploy" autoscaled
···
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
hpa-nginx-deploy Deployment/hpa-nginx-deploy 10% 0% 1 10 13s
此命令創(chuàng)建了一個關聯(lián)資源 hpa-nginx-deploy 的HPA,最小的 pod 副本數(shù)為1,最大為10。HPA會根據(jù)設定的 cpu使用率(10%)動態(tài)的增加或者減少pod數(shù)量。
現(xiàn)在我們來增大負載進行測試,我們來創(chuàng)建一個busybox,并且循環(huán)訪問上面創(chuàng)建的服務。
$ kubectl run -i --tty load-generator --image=busybox /bin/sh
If you don't see a command prompt, try pressing enter.
/ # while true; do wget -q -O- http://172.16.255.60:4000; done
下圖可以看到,HPA已經(jīng)開始工作。
kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
hpa-nginx-deploy Deployment/hpa-nginx-deploy 10% 29% 1 10 27m
同時我們查看相關資源hpa-nginx-deploy的副本數(shù)量,副本數(shù)量已經(jīng)從原來的1變成了3。
$ kubectl get deployment hpa-nginx-deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hpa-nginx-deploy 3 3 3 3 4d
同時再次查看HPA,由于副本數(shù)量的增加,使用率也保持在了10%左右。
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
hpa-nginx-deploy Deployment/hpa-nginx-deploy 10% 9% 1 10 35m
同樣的這個時候我們來關掉busybox來減少負載,然后等待一段時間觀察下HPA和Deployment對象
$ kubectl get hpa
NAME REFERENCE TARGET CURRENT MINPODS MAXPODS AGE
hpa-nginx-deploy Deployment/hpa-nginx-deploy 10% 0% 1 10 48m
$ kubectl get deployment hpa-nginx-deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
hpa-nginx-deploy 1 1 1 1 4d
可以看到副本數(shù)量已經(jīng)由3變?yōu)?。
2 不使用kubectl autoscale
使用已經(jīng)創(chuàng)建成功的hpa
$ kubectl get hpa hpa-nginx-deploy -o yaml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
creationTimestamp: 2017-06-29T08:04:08Z
name: nginxtest
namespace: default
resourceVersion: "951016361"
selfLink: /apis/autoscaling/v1/namespaces/default/horizontalpodautoscalers/nginxtest
uid: 86febb63-5ca1-11e7-aaef-5254004e79a3
spec:
maxReplicas: 5 //資源最大副本數(shù)
minReplicas: 1 //資源最小副本數(shù)
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment //需要伸縮的資源類型
name: nginxtest //需要伸縮的資源名稱
targetCPUUtilizationPercentage: 50 //觸發(fā)伸縮的cpu使用率
status:
currentCPUUtilizationPercentage: 48 //當前資源下pod的cpu使用率
currentReplicas: 1 //當前的副本數(shù)
desiredReplicas: 2 //期望的副本數(shù)
lastScaleTime: 2017-07-03T06:32:19Z
使用生成的HPA重新創(chuàng)建一個HPA
刪除hpa
kubectl delete hpa hpa-demo
刪除deployments
kubectl delete -f hpa-demo.yaml
將生成的yaml追加到hap-deploy-demo.yaml,得到的內(nèi)容如下:
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: hpa-demo
labels:
app: hpa
spec:
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: 100m
ports:
- containerPort: 80
---
5apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: hpa-demo
namespace: default
spec:
maxReplicas: 10
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hpa-demo
targetCPUUtilizationPercentage: 5
重新創(chuàng)建
kubectl create -f hpa-demo.yaml
三、Job 和 Cronjob 的使用
Job負責處理任務,即僅執(zhí)行一次的任務,它保證批處理任務的一個或多個Pod成功結束。而CronJob則就是在Job上加上了時間調(diào)度。
1 Job
我們用Job這個資源對象來創(chuàng)建一個任務,我們定一個Job來執(zhí)行一個倒計時的任務,定義YAML文件:
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template:
metadata:
name: job-demo
spec:
restartPolicy: Never
containers:
- name: counter
image: busybox
command:
- "bin/sh"
- "-c"
- "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"
注意Job的RestartPolicy僅支持Never和OnFailure兩種,不支持Always,我們知道Job就相當于來執(zhí)行一個批處理任務,執(zhí)行完就結束了,如果支持Always的話是不是就陷入了死循環(huán)了?
然后來創(chuàng)建該Job,保存為job-demo.yaml:
$ kubectl create -f ./job.yaml
job "job-demo" created
然后我們可以查看當前的Job資源對象:
$ kubectl get jobs
$ kubectl describe job job-demo
注意查看我們的Pod的狀態(tài),同樣我們可以通過kubectl logs來查看當前任務的執(zhí)行結果。
$ kubectl logs job-demo-p6zst
2 CronJob
期性地在給定時間點運行。這個實際上和我們Linux中的crontab就非常類似了。
一個CronJob對象其實就對應中crontab文件中的一行,它根據(jù)配置的時間格式周期性地運行一個Job,格式和crontab也是一樣的。
crontab的格式如下:
分 時 日 月 星期 要運行的命令
第1列分鐘0~59
第2列小時0~23)
第3列日1~31
第4列月1~12
第5列星期0~7(0和7表示星期天)
第6列要運行的命令
現(xiàn)在,我們用CronJob來管理我們上面的Job任務,
apiVersion: batch/v2alpha1
kind: CronJob
metadata:
name: cronjob-demo
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: hello
image: busybox
args:
- "bin/sh"
- "-c"
- "for i in 9 8 7 6 5 4 3 2 1; do echo $i; done"
我們這里的Kind是CronJob了,要注意的是.spec.schedule字段是必須填寫的,用來指定任務運行的周期,格式就和crontab一樣,另外一個字段是.spec.jobTemplate, 用來指定需要運行的任務,格式當然和Job是一致的。
還有一些值得我們關注的字段.spec.successfulJobsHistoryLimit和.spec.failedJobsHistoryLimit,表示歷史限制,是可選的字段。它們指定了可以保留多少完成和失敗的Job,默認沒有限制,所有成功和失敗的Job都會被保留。然而,當運行一個Cron Job時,Job可以很快就堆積很多,所以一般推薦設置這兩個字段的值。如果設置限制的值為 0,那么相關類型的Job完成后將不會被保留。
接下來我們來創(chuàng)建這個cronjob
$ kubectl create -f cronjob-demo.yaml
cronjob "cronjob-demo" created
當然,也可以用kubectl run來創(chuàng)建一個CronJob:
kubectl run hello --schedule="*/1 * * * *" --restart=OnFailure --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST-SCHEDULE
hello */1 * * * * False 0 <none>
$ kubectl get jobs
NAME DESIRED SUCCESSFUL AGE
hello-1202039034 1 1 49s
$ pods=$(kubectl get pods --selector=job-name=hello-1202039034 --output=jsonpath={.items..metadata.name} -a)
$ kubectl logs $pods
Mon Aug 29 21:34:09 UTC 2016
Hello from the Kubernetes cluster
一旦不再需要 Cron Job,簡單地可以使用 kubectl 命令刪除它:
$ kubectl delete cronjob hello
cronjob "hello" deleted
這將會終止正在創(chuàng)建的 Job。
然而,運行中的 Job 將不會被終止,不會刪除 Job 或 它們的 Pod。為了清理那些 Job 和 Pod,需要列出該 Cron Job 創(chuàng)建的全部 Job,然后刪除它們:
$ kubectl get jobs
NAME DESIRED SUCCESSFUL AGE
hello-1201907962 1 1 11m
hello-1202039034 1 1 8m
...
$ kubectl delete jobs hello-1201907962 hello-1202039034 ...
job "hello-1201907962" deleted
job "hello-1202039034" deleted
...
一旦 Job 被刪除,由 Job 創(chuàng)建的 Pod 也會被刪除。注意,所有由名稱為 “hello” 的 Cron Job 創(chuàng)建的 Job 會以前綴字符串 “hello-” 進行命名。如果想要刪除當前 Namespace 中的所有 Job,可以通過命令 kubectl delete jobs --all 立刻刪除它們。
CronJob的某個job與pod之間的對應關系如下:
$ kubectl get cronjob
$ kubectl get jobs
$ kubectl get pods
看下job的對應的pod的log,無法直接查看某個cronjob的log
$ kubectl logs cronjob-demo-12XXX
刪除CronJob
$ kubectl delte cronjob cronjob-demo
或者
$ kubectl delete -f cronjob-demo.yaml
四、Service
在沒有使用Kubernetes之前,我相信可能很多同學都遇到過這樣的問題,不一定是IP變化的問題,比如我們在部署一個WEB服務的時候,前端一般部署一個Nginx作為服務的入口,然后Nginx后面肯定就是掛載的這個服務的大量后端,很早以前我們可能是去手動更改Nginx配置中的upstream選項,來動態(tài)改變提供服務的數(shù)量,到后面出現(xiàn)了一些服務發(fā)現(xiàn)的工具,比如Consul、ZooKeeper還有我們熟悉的etcd等工具,有了這些工具過后我們就可以只需要把我們的服務注冊到這些服務發(fā)現(xiàn)中心去就可以,然后讓這些工具動態(tài)的去更新Nginx的配置就可以了,我們完全不用去手工的操作了,是不是非常方便。
同樣的,要解決我們上面遇到的問題是不是實現(xiàn)一個服務發(fā)現(xiàn)的工具也可以解決???沒錯的,當我們Pod被銷毀或者新建過后,我們可以把這個Pod的地址注冊到這個服務發(fā)現(xiàn)中心去就可以,但是這樣的話我們的前端的Pod結合就不能直接去連接后臺的Pod集合了是吧,應該連接到一個能夠做服務發(fā)現(xiàn)的中間件上面,對吧?
沒錯,Kubernetes集群就為我們提供了這樣的一個對象
- Service,Service是一種抽象的對象,它定義了一組Pod的邏輯集合和一個用于訪問它們的策略,其實這個概念和微服務非常類似。一個Serivce下面包含的Pod集合一般是由Label Selector來決定的。
- 比如我們上面的例子,假如我們后端運行了3個副本,這些副本都是可以替代的,因為前端并不關心它們使用的是哪一個后端服務。盡管由于各種原因后端的Pod集合會發(fā)送變化,但是前端卻不需要知道這些變化,也不需要自己用一個列表來記錄這些后端的服務,Service的這種抽象就可以幫我們達到這種解耦的目的。
1.三種IP
- Node IP:Node節(jié)點的IP地址
- Pod IP: Pod的IP地址
- Cluster IP: Service的IP地址
首先,Node IP是Kubernetes集群中節(jié)點的物理網(wǎng)卡IP地址(一般為內(nèi)網(wǎng)),所有屬于這個網(wǎng)絡的服務器之間都可以直接通信,所以Kubernetes集群外要想訪問Kubernetes集群內(nèi)部的某個節(jié)點或者服務,肯定得通過Node IP進行通信(這個時候一般是通過外網(wǎng)IP了)
然后Pod IP是每個Pod的IP地址,它是Docker Engine根據(jù)docker0網(wǎng)橋的IP地址段進行分配的(我們這里使用的是flannel這種網(wǎng)絡插件保證所有節(jié)點的Pod IP不會沖突)
最后Cluster IP是一個虛擬的IP,僅僅作用于Kubernetes Service這個對象,由Kubernetes自己來進行管理和分配地址,當然我們也無法ping這個地址,他沒有一個真正的實體對象來響應,他只能結合Service Port來組成一個可以通信的服務。
2.定義Service
先創(chuàng)建pods
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deploy
namespace: test
labels:
app: nginx-demo
spec:
replicas: 3
revisionHistoryLimit: 15
minReadySeconds: 5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: nginxweb
創(chuàng)建Deployment
$ kubectl create -f deploy-demo.yaml
創(chuàng)建service
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
selector:
app: nginx
ports:
- protocol: TCP
# 該service的端口
port: 80
#匹配到app: nginx的容器的端口
targetPort: nginxweb
$ kubectl create -f service-demo.yaml
查看
$ kubectl get svc
$ kubectl describe svc myservice
測試Cluster IP
$ kubectl run -it testservice --image=busybox /bin/bash
$ wget -O- -q http://10.104.27.136:80
3.kube-proxy
在Kubernetes集群中,每個Node會運行一個kube-proxy進程, 負責為Service實現(xiàn)一種 VIP(虛擬 IP,就是我們上面說的clusterIP)的代理形式,現(xiàn)在的Kubernetes中默認是使用的iptables這種模式來代理。
這種模式,kube-proxy會監(jiān)視Kubernetes master對 Service 對象和 Endpoints 對象的添加和移除。
對每個 Service,它會添加上 iptables 規(guī)則,從而捕獲到達該 Service 的 clusterIP(虛擬 IP)和端口的請求,進而將請求重定向到 Service 的一組 backend 中的某一個個上面。
對于每個 Endpoints 對象,它也會安裝 iptables 規(guī)則,這個規(guī)則會選擇一個 backend Pod。
默認的策略是,隨機選擇一個 backend。 我們也可以實現(xiàn)基于客戶端 IP 的會話親和性,可以將 service.spec.sessionAffinity 的值設置為 “ClientIP” (默認值為 “None”)。
如果最開始選擇的 Pod 沒有響應,iptables 代理能夠自動地重試另一個 Pod,所以它需要依賴 readiness probes。
4.Service 類型
我們在定義Service的時候可以指定一個自己需要的類型的Service,如果不指定的話默認是ClusterIP類型。
我們可以使用的服務類型如下:
- ClusterIP:通過集群的內(nèi)部 IP 暴露服務,選擇該值,服務只能夠在集群內(nèi)部可以訪問,這也是默認的ServiceType。
- NodePort:通過每個 Node 節(jié)點上的 IP 和靜態(tài)端口(NodePort)暴露服務。NodePort 服務會路由(會暴露一個node的端口)到 ClusterIP 服務,這個 ClusterIP 服務會自動創(chuàng)建。通過請求 node ip:node port,可以從集群的外部訪問一個 NodePort 服務。
- LoadBalancer:使用云提供商的負載局衡器,可以向外部暴露服務。外部的負載均衡器可以路由到 NodePort 服務和 ClusterIP 服務,這個需要結合具體的云廠商進行操作。
- ExternalName:通過返回 CNAME 和它的值,可以將服務映射到 externalName 字段的內(nèi)容(例如, foo.bar.example.com)。沒有任何類型代理被創(chuàng)建,這只有 Kubernetes 1.7 或更高版本的 kube-dns 才支持。
5.NodePort 類型
如果設置 type 的值為 “NodePort”,Kubernetes master 將從給定的配置范圍內(nèi)(默認:30000-32767)分配端口,每個 Node 將從該端口(每個 Node 上的同一端口)代理到 Service。
- 該端口將通過 Service 的 spec.ports[*].nodePort 字段被指定,如果不指定的話會自動生成一個端口。
需要注意的是,Service 將能夠通過 :spec.ports[].nodePort 和 spec.clusterIp:spec.ports[].port 而對外可見。
接下來我們來給大家創(chuàng)建一個NodePort的服務來訪問我們前面的Nginx服務:(保存為service-demo.yaml)
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
selector:
app: myapp
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
name: myapp-http
創(chuàng)建該Service:
$ kubectl create -f service-demo.yaml
然后我們可以查看Service對象信息:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d
myservice NodePort 10.104.57.198 <none> 80:32560/TCP 14h
我們可以看到myservice的 TYPE 類型已經(jīng)變成了NodePort,后面的PORT(S)部分也多了一個 32560 的映射端口。
- 直接通過node ip:32560即可訪問
6.ExternalName
ExternalName 是 Service 的特例,它沒有 selector,也沒有定義任何的端口和 Endpoint。 對于運行在集群外部的服務,它通過返回該外部服務的別名這種方式來提供服務。
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
當查詢主機 my-service.prod.svc.cluster.local (后面服務發(fā)現(xiàn)的時候我們會再深入講解)時,集群的 DNS 服務將返回一個值為 my.database.example.com 的 CNAME 記錄。 訪問這個服務的工作方式與其它的相同,唯一不同的是重定向發(fā)生在 DNS 層,而且不會進行代理或轉發(fā)。
如果后續(xù)決定要將數(shù)據(jù)庫遷移到 Kubernetes 集群中,可以啟動對應的 Pod,增加合適的 Selector 或 Endpoint,修改 Service 的 type,完全不需要修改調(diào)用的代碼,這樣就完全解耦了。
五、ConfigMap
資源對象:ConfigMap,我們知道許多應用經(jīng)常會有從配置文件、命令行參數(shù)或者環(huán)境變量中讀取一些配置信息,這些配置信息我們肯定不會直接寫死到應用程序中去的,比如你一個應用連接一個redis服務,下一次想更換一個了的,還得重新去修改代碼,重新制作一個鏡像,這肯定是不可取的,而ConfigMap就給我們提供了向容器中注入配置信息的能力,不僅可以用來保存單個屬性,也可以用來保存整個配置文件,比如我們可以用來配置一個redis服務的訪問地址,也可以用來保存整個redis的配置文件。
1.通過yaml文件的方式創(chuàng)建
ConfigMap 資源對象使用key-value形式的鍵值對來配置數(shù)據(jù),這些數(shù)據(jù)可以在Pod里面使用,ConfigMap和我們后面要講到的Secrets比較類似,一個比較大的區(qū)別是ConfigMap可以比較方便的處理一些非敏感的數(shù)據(jù),比如密碼之類的還是需要使用Secrets來進行管理。
我們來舉個例子說明下ConfigMap的使用方法:
kind: ConfigMap
apiVersion: v1
metadata:
name: cm-demo
namespace: default
data:
data.1: hello
data.2: world
config: |
property.1=value-1
property.2=value-2
property.3=value-3
其中配置數(shù)據(jù)在data屬性下面進行配置,前兩個被用來保存單個屬性,后面一個被用來保存一個配置文件。
使用kubectl create -f xx.yaml來創(chuàng)建上面的ConfigMap對象
查詢configmap
$ kubectl get configmap
描述configmap
$ kubectl describe configmap cm-demo1
2.通過目錄和命令行創(chuàng)建
我們可以看到可以從一個給定的目錄來創(chuàng)建一個ConfigMap對象,比如我們有一個testcm的目錄,該目錄下面包含一些配置文件,redis和mysql的連接信息,如下:
$ ls testcm
redis.conf
mysql.conf
$ cat testcm/redis.conf
host=127.0.0.1
port=6379
$ cat testcm/mysql.conf
host=127.0.0.1
port=3306
然后我們可以使用from-file關鍵字來創(chuàng)建包含這個目錄下面所以配置文件的ConfigMap:
$ kubectl create configmap cm-demo1 --from-file=testcm
configmap "cm-demo1" created
其中from-file參數(shù)指定在該目錄下面的所有文件都會被用在ConfigMap里面創(chuàng)建一個鍵值對,鍵的名字就是文件名,值就是文件的內(nèi)容。
創(chuàng)建完成后,同樣我們可以使用如下命令來查看ConfigMap列表:
$ kubectl get configmap
NAME DATA AGE
cm-demo1 2 17s
可以看到已經(jīng)創(chuàng)建了一個cm-demo1的ConfigMap對象,然后可以使用describe命令查看詳細信息:
kubectl describe configmap cm-demo1
Name: cm-demo1
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
mysql.conf:
----
host=127.0.0.1
port=3306
redis.conf:
----
host=127.0.0.1
port=6379
Events: <none>
我們可以看到兩個key是testcm目錄下面的文件名稱,對應的value值的話就是文件內(nèi)容,這里值得注意的是如果文件里面的配置信息很大的話,describe的時候可能不會顯示對應的值,要查看鍵值的話,可以使用如下命令:
$ kubectl get configmap cm-demo1 -o yaml
apiVersion: v1
data:
mysql.conf: |
host=127.0.0.1
port=3306
redis.conf: |
host=127.0.0.1
port=6379
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:24:36Z
name: cm-demo1
namespace: default
resourceVersion: "3109975"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo1
uid: 6e0f4d82-6fef-11e8-a101-525400db4df7
3.通過配置文件和命令行創(chuàng)建
以上面的配置文件為例,我們創(chuàng)建一個redis的配置的一個單獨ConfigMap對象:
$ kubectl create configmap cm-demo2 --from-file=testcm/redis.conf
configmap "cm-demo2" created
$ kubectl get configmap cm-demo2 -o yaml
apiVersion: v1
data:
redis.conf: |
host=127.0.0.1
port=6379
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:34:29Z
name: cm-demo2
namespace: default
resourceVersion: "3110758"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo2
uid: cf59675d-6ff0-11e8-a101-525400db4df7
我們可以看到一個關聯(lián)redis.conf文件配置信息的ConfigMap對象創(chuàng)建成功了,另外值得注意的是–from-file這個參數(shù)可以使用多次,比如我們這里使用兩次分別指定redis.conf和mysql.conf文件,就和直接指定整個目錄是一樣的效果了。
4.通過命令行的–from-literal進行創(chuàng)建
可以直接使用字符串進行創(chuàng)建,通過–from-literal參數(shù)傳遞配置信息,同樣的,這個參數(shù)可以使用多次,格式如下:
$ kubectl create configmap cm-demo3 --from-literal=db.host=localhost --from-literal=db.port=3306
configmap "cm-demo3" created
$ kubectl get configmap cm-demo3 -o yaml
apiVersion: v1
data:
db.host: localhost
db.port: "3306"
kind: ConfigMap
metadata:
creationTimestamp: 2018-06-14T16:43:12Z
name: cm-demo3
namespace: default
resourceVersion: "3111447"
selfLink: /api/v1/namespaces/default/configmaps/cm-demo3
uid: 06eeec7e-6ff2-11e8-a101-525400db4df7
5.如何在pod中使用?
ConfigMap這些配置數(shù)據(jù)可以通過很多種方式在Pod里使用,主要有以下幾種方式:
- 設置環(huán)境變量的值
- 在容器里設置命令行參數(shù)
- 在數(shù)據(jù)卷里面創(chuàng)建config文件
(1)設置環(huán)境變量的值
apiVersion: v1
kind: Pod
metadata:
name: testcm1-pod
spec:
containers:
- name: testcm1
image: busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.port
envFrom:
- configMapRef:
name: cm-demo1
這個Pod運行后會輸出如下幾行:
$ kubectl logs testcm1-pod
......
DB_HOST=localhost
DB_PORT=3306
mysql.conf=host=127.0.0.1
port=3306
redis.conf=host=127.0.0.1
port=6379
......
我們可以看到DB_HOST和DB_PORT都已經(jīng)正常輸出了,另外的環(huán)境變量是因為我們這里直接把cm-demo1給注入進來了,所以把他們的整個鍵值給輸出出來了,這也是符合預期的。
(2)在容器里設置命令行參數(shù)
ConfigMap也可以被用來設置容器中的命令或者參數(shù)值,如下Pod:
apiVersion: v1
kind: Pod
metadata:
name: testcm2-pod
spec:
containers:
- name: testcm2
image: busybox
command: [ "/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)" ]
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.host
- name: DB_PORT
valueFrom:
configMapKeyRef:
name: cm-demo3
key: db.port
運行這個Pod后會輸出如下信息:
$ kubectl logs testcm2-pod
localhost 3306
(3)在數(shù)據(jù)卷里面創(chuàng)建config文件
外一種是非常常見的使用ConfigMap的方式:通過數(shù)據(jù)卷使用,在數(shù)據(jù)卷里面使用ConfigMap,就是將文件填入數(shù)據(jù)卷,在這個文件中,鍵就是文件名,鍵值就是文件內(nèi)容:
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
spec:
containers:
- name: testcm4
image: busybox
command: ["/bin/sh", "-c", "cat /etc/config/redis.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
# 與volumeMounts.name保持一致
- name: config-volume
configMap:
name: cm-demo3
運行這個Pod的,查看日志:
$ kubectl logs testcm3-pod
host=127.0.0.1
port=6379
當然我們也可以在ConfigMap值被映射的數(shù)據(jù)卷里去控制路徑,如下Pod定義:
apiVersion: v1
kind: Pod
metadata:
name: testcm4-pod
spec:
containers:
- name: testcm4
image: busybox
command: [ "/bin/sh","-c","cat /etc/config/path/to/msyql.conf" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: cm-demo1
items:
- key: mysql.conf
path: path/to/msyql.conf
運行這個Pod的,查看日志:文章來源:http://www.zghlxwxcb.cn/news/detail-847479.html
$ kubectl logs testcm4-pod
host=127.0.0.1
port=3306
另外需要注意的是,當ConfigMap以數(shù)據(jù)卷的形式掛載進Pod的時,這時更新ConfigMap(或刪掉重建ConfigMap),Pod內(nèi)掛載的配置信息會熱更新。這時可以增加一些監(jiān)測配置文件變更的腳本,然后reload對應服務。文章來源地址http://www.zghlxwxcb.cn/news/detail-847479.html
到了這里,關于K8S:常用資源對象操作的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!