Kubernetes使用者指南(三)–在生產環境中使用Pod來工作、管理部署
版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/qq1010885678/article/details/49156557
一、在生產環境中使用Pod來工作
本節將介紹一些在生產環境中執行應用非常有用的功能。
1、持久化儲存
容器的檔案系統只有當容器正常執行時有效,一旦容器奔潰或者重啟,所有對檔案系統的修改將會丟失,從一個原始的檔案系統重新開始。
所以為了實現更多的持久化資訊,在檔案系統之外你需要一個volume,volume對有狀態的應用來說是非常重要的,例如鍵值對儲存和資料庫等。
例如,Redis是一個鍵值對的儲存庫,在guestbook這個例子中使用過。
我們可以通過一下的配置新增一個volume來儲存需要持久化的資料:
apiVersion: v1
kind: ReplicationController
metadata:
name: redis
spec:
template:
metadata:
labels:
app: redis
tier: backend
spec:
# Provision a fresh volume for the pod
volumes:
– name: data
emptyDir: {}
containers:
– name: redis
image: kubernetes/redis:v1
ports:
– containerPort: 6379
# Mount the volume into the pod
volumeMounts:
– mountPath: /redis-master-data
kind: ReplicationController
metadata:
name: redis
spec:
template:
metadata:
labels:
app: redis
tier: backend
spec:
# Provision a fresh volume for the pod
volumes:
– name: data
emptyDir: {}
containers:
– name: redis
image: kubernetes/redis:v1
ports:
– containerPort: 6379
# Mount the volume into the pod
volumeMounts:
– mountPath: /redis-master-data
name: data # must match the name of the volume, above
emptyDir這列的生命週期是隨著pod的生命週期的,比任何一個容器的生命週期都要長,所以當容器奔潰或者重啟的時候,這些持久化資料依然存在。
除了emptyDir提供的本地磁碟儲存之外,k8s還提供了很多不同的網路儲存方案,包括GCE的PD和EC2的EBS,這些是儲存關鍵資料的首先方案並且會自動處理一些細節,例如在節點上mount和unmout裝置。
從這裡看配置volume的全部資訊:
2、分配證書
為了和其他的應用、資料和和伺服器進行互相驗證,很多應用都需要證書,例如密碼、OAuth tokens和TLS keys等。
將這些證書儲存在容器的映象或者環境變數中是不理想的,因為這些證書可以被任何容器從映象、配置檔案、主機檔案系統或者主機的Docker守護程式中複製出來。
為了方便容器之間互動敏感的證書,k8s提供了一個名為secrets的機制。
Secret也是k8s中的一個資源,一組map型別的資料,例如,一個簡單的包含使用者名稱和密碼的Secret可以這樣定義:
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMQ0K
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
password: dmFsdWUtMg0K
username: dmFsdWUtMQ0K
和其他的資源一樣,Secret也可以通過create命令來例項化,也可以通過get命令來檢視:
$ kubectl create -f ./secret.yaml
secrets/mysecret
$ kubectl get secrets
NAME TYPE DATA
default-token-v9pyz kubernetes.io/service-account-token 2
mysecret Opaque 2
secrets/mysecret
$ kubectl get secrets
NAME TYPE DATA
default-token-v9pyz kubernetes.io/service-account-token 2
mysecret Opaque 2
你需要在Pod或者Pod Template中引用這個Secret才能使用它,secret列使你可以在容器中將它像記憶體目錄一樣進行掛載。
apiVersion: v1
kind: ReplicationController
metadata:
name: redis
spec:
template:
metadata:
labels:
app: redis
tier: backend
spec:
volumes:
– name: data
emptyDir: {}
– name: supersecret
secret:
secretName: mysecret
containers:
– name: redis
image: kubernetes/redis:v1
ports:
– containerPort: 6379
# Mount the volume into the pod
volumeMounts:
– mountPath: /redis-master-data
name: data # must match the name of the volume, above
– mountPath: /var/run/secrets/super
kind: ReplicationController
metadata:
name: redis
spec:
template:
metadata:
labels:
app: redis
tier: backend
spec:
volumes:
– name: data
emptyDir: {}
– name: supersecret
secret:
secretName: mysecret
containers:
– name: redis
image: kubernetes/redis:v1
ports:
– containerPort: 6379
# Mount the volume into the pod
volumeMounts:
– mountPath: /redis-master-data
name: data # must match the name of the volume, above
– mountPath: /var/run/secrets/super
name: supersecret
點選這些檢視更加詳細的資訊:
3、通過私有的映象倉庫進行校驗
Secrets也可以用來通過映象倉庫的驗證(image
registry credentials)。
registry credentials)。
首先,穿件一個.dockercfg檔案,例如執行docker login <registry.domain>。
之後將.dockercfg的執行結果輸入到一個Secret資源中,示例如下:
$ docker login
Username: janedoe
Password: ●●●●●●●●●●●
Email: jdoe@example.com
WARNING: login credentials saved in /Users/jdoe/.dockercfg.
Login Succeeded
Username: janedoe
Password: ●●●●●●●●●●●
Email: jdoe@example.com
WARNING: login credentials saved in /Users/jdoe/.dockercfg.
Login Succeeded
$ echo $(cat ~/.dockercfg)
{ “https://index.docker.io/v1/“: { “auth”: “ZmFrZXBhc3N3b3JkMTIK”, “email”: “jdoe@example.com” } }
$ cat ~/.dockercfg | base64
eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K
$ cat > /tmp/image-pull-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
data:
.dockercfg: eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K
type: kubernetes.io/dockercfg
EOF
$ kubectl create -f ./image-pull-secret.yaml
secrets/myregistrykey
現在,你就可以建立通過imagePullSecrets引用secret的Pod:
apiVersion: v1
kind: Pod
metadata:
name: foo
spec:
containers:
– name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
– name: myregistrykey
kind: Pod
metadata:
name: foo
spec:
containers:
– name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
– name: myregistrykey
4、輔助容器
Pods提供了集中執行多個容器的能力,它們可以在主機上被用來做應用的垂直整合。
但是Pods設計的原始動機是為協助主應用程式提供幫助,典型的例子有data pullers、data pushers和proxies。
這些代表性的容器經常通過檔案系統和其他容器進行互動,將相同的卷掛載到不同的容器中就可以做到這一點。
這種模式的一個例子是使用git來進行程式碼管理的的web服務:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
template:
metadata:
labels:
app: nginx
spec:
volumes:
– name: www-data
emptyDir: {}
containers:
– name: nginx
image: nginx
# This container reads from the www-data volume
volumeMounts:
– mountPath: /srv/www
name: www-data
readOnly: true
– name: git-monitor
image: myrepo/git-monitor
env:
– name: GIT_REPO
value: http://github.com/some/repo.git
# This container writes to the www-data volume
volumeMounts:
– mountPath: /data
name: www-data
kind: ReplicationController
metadata:
name: my-nginx
spec:
template:
metadata:
labels:
app: nginx
spec:
volumes:
– name: www-data
emptyDir: {}
containers:
– name: nginx
image: nginx
# This container reads from the www-data volume
volumeMounts:
– mountPath: /srv/www
name: www-data
readOnly: true
– name: git-monitor
image: myrepo/git-monitor
env:
– name: GIT_REPO
value: http://github.com/some/repo.git
# This container writes to the www-data volume
volumeMounts:
– mountPath: /data
name: www-data
更多的使用例子在:
5、資源分配
k8s的Scheduler只會在擁有足夠的CPU和記憶體的節點上佈置應用,但是要做到這一點,Scheduler就必須知道它們需要多少資源。
如果指定的CPU資源太少,當有很多容器被啟動在同一個節點上的時候就會出現CPU匱缺。
同樣的,當沒有足夠的記憶體在請求的時候,容器將會因為不可預料的記憶體溢位而掛掉,尤其是需要大記憶體的應用。
如果沒有明確指定資源需求,名義上,資源分配的數量是預設的(這個預設值是通過預設Namespace下的LimitRange應用的,可以通過kubectl
describe limitrange limits來檢視)。
describe limitrange limits來檢視)。
你可以通過以下的方式明確地指定資源的需求量:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
resources:
limits:
# cpu units are cores
cpu: 500m
# memory units are bytes
memory: 64Mi
requests:
# cpu units are cores
cpu: 500m
# memory units are bytes
memory: 64Mi
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
resources:
limits:
# cpu units are cores
cpu: 500m
# memory units are bytes
memory: 64Mi
requests:
# cpu units are cores
cpu: 500m
# memory units are bytes
memory: 64Mi
容器請求的資源超出規定的限制之後會出現記憶體溢位的錯誤而掛掉,所以指定的值略高於預期準備指定的值會普遍提高可靠性。
通過規定資源的需求量,保證了Pod在需要的時候可以有足夠的資源來使用。
更多資源限制和資源需求量的設定請看:
如果你不確定多少資源需要分配,剛開始你可以不指定多少資源分配直接啟動應用,之後通過
來觀察和確定出合適的值。
6、活躍度和狀態資訊檢查(又名健康狀態檢查)
許多應用執行了很長一段時間後有可能會因為很多原因最後變為不可用的,除了重啟之外無法恢復還原。
k8s提供了
用來檢查和補救以上的情況。
可以使用HTTP進行常規的應用檢查,定義如下:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
livenessProbe:
httpGet:
# Path to probe; should be cheap, but representative of typical behavior
path: /index.html
port: 80
initialDelaySeconds: 30
timeoutSeconds: 1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
livenessProbe:
httpGet:
# Path to probe; should be cheap, but representative of typical behavior
path: /index.html
port: 80
initialDelaySeconds: 30
timeoutSeconds: 1
至於其他的時間,應用可能只是暫時無法提供服務,並且會進行自我恢復。
這個時候,你肯定不願去直接關掉應用,但是也不要給他傳送請求,因為它不會馬上回復你甚至根本不響應。
一個典型的場景是當應用初始化的時候載入大量資料或者配置檔案。
k8s提供了Readiness probes來檢查和緩解這種情況,Readiness probes的配置和Liveness probes大致是相同的,只是使用readinessProbe欄位。
Pod中的容器將會通過k8s服務來報告它們現在是否準備就緒。
更多詳細請看:
7、生命週期中的鉤子和終止注意
節點和應用可能在任何時間點失敗掛掉,但是對於乾淨地關閉,對很多應用來說都是有益的。
例如當故意關掉應用的時候,完成正在處理中的請求。
k8s提供了兩種通知來實現:
- k8s將會給應用傳送SIGTERM訊號,可以用來正確、優雅地關閉應用。當應用沒有提前終止的時候,SIGKILL將會傳送一個配置好的時間數(預設為30秒,通過spec.terminationGracePeriodSeconds配置)。
-
k8s提供了pre-stop
lifecycle hook 的配置宣告,將會在傳送SIGTERM之前執行。
pre-stop hook的配置方式和probes大致相同,但是沒有timing-related引數,例如:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
lifecycle:
preStop:
exec:
# SIGTERM triggers a quick exit; gracefully terminate instead
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
lifecycle:
preStop:
exec:
# SIGTERM triggers a quick exit; gracefully terminate instead
command: [“/usr/sbin/nginx”,”-s”,”quit”]
8、終止資訊
實現一個高可用的機制是必要的,尤其是對於一些十分活躍的應用。
快速DEBUG是十分重要的,k8s當出現致命的錯誤時可以快速debug,並且在kubectl或者UI中顯示,除了一般的日誌收集。
一個容器掛掉之後通過terminationMessagePath配置“寫下它的遺言”這是有可能的,就像列印錯誤、異常和堆疊資訊一樣。
預設的路勁為/dev/termination-log。
以下是一個小例子:
apiVersion: v1
kind: Pod
metadata:
name: pod-w-message
spec:
containers:
– name: messager
image: “ubuntu:14.04“
command: [“/bin/sh”,”-c”]
kind: Pod
metadata:
name: pod-w-message
spec:
containers:
– name: messager
image: “ubuntu:14.04“
command: [“/bin/sh”,”-c”]
args: [“sleep 60 && /bin/echo Sleep expired > /dev/termination-log”]
這些訊息的最後部分會使用其他的規定來單獨儲存:
$ kubectl create -f ./pod.yaml
pods/pod-w-message
$ sleep 70
$ kubectl get pods/pod-w-message -o go-template=“{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}“
Sleep expired
$ kubectl get pods/pod-w-message -o go-template=“{{range .status.containerStatuses}}{{.lastState.terminated.exitCode}}{{end}}“
0
pods/pod-w-message
$ sleep 70
$ kubectl get pods/pod-w-message -o go-template=“{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}“
Sleep expired
$ kubectl get pods/pod-w-message -o go-template=“{{range .status.containerStatuses}}{{.lastState.terminated.exitCode}}{{end}}“
0
二、管理部署
現在你已經並通過Service與外界相連線。
那麼現在可以準備怎麼辦呢?
k8s提供了一系列的工具幫助你管理應用的部署,包括擴充套件和更新。
除了這些,我們將會在
和
中討論更多的細節。
1、組織資源的配置
很多應用要求建立許多資源,例如RC和SVC。
可以將這些資源在同一個檔案中分組來簡化對他們的管理(在YAML檔案中通過 — 來分隔)。
如下面的例子:
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
– port: 80
selector:
app: nginx
–—
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
– port: 80
selector:
app: nginx
–—
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx
ports:
– containerPort: 80
多個資源的建立方式和之前的建立單個資源一樣:
$ kubectl create -f ./nginx-app.yaml
services/my-nginx-svc
replicationcontrollers/my-nginx
services/my-nginx-svc
replicationcontrollers/my-nginx
這些資源將會按照檔案中的順序來建立。
所以,第一個定義SVC是最好的,因為這樣一來Scheduler就可以使這個RC建立的Pods都通過SVC來連線。
kubectl create命令也接受多個-f引數:
$ kubectl create -f ./nginx-svc.yaml -f ./nginx-rc.yaml
也可以指定一個目錄而不僅僅是一個檔案:
$ kubectl create -f ./nginx/
kubectl將會讀取所有字尾名為.yaml、.yml、.json的檔案。
這是一個推薦的做法,來把一個微服務或者應用中相關的資源在一個檔案中順序定義,並且在一個目錄中將這些和你的應用相關的檔案分組。
如果每層中的應用都通過DNS互相連線繫結,那麼你就可以十分簡單地部署所有元件。
一個URL也可以作為配置檔案的源,例如直接使用簽入git中的配置檔案來部署:
$ kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes/master/docs/user-guide/replication.yaml
replicationcontrollers/nginx
2、Kubectl中的批量操作
kubectl並不只是僅僅能夠執行批量建立資源的操作。
它也可以將資源的名字從配置檔案中抽取出來,用來進行一些其他的操作,特別是要刪除你建立的相同的資源的時候:
$ kubectl delete -f ./nginx/
replicationcontrollers/my-nginx
services/my-nginx-svc
replicationcontrollers/my-nginx
services/my-nginx-svc
在這裡例子中,只有兩個資源被刪除了,同樣的效果在命令列中也可以通過資源的名稱很容易地操作:
$ kubectl delete replicationcontrollers/my-nginx services/my-nginx-svc
對於資源數量很大的情況,另外一種是可以使用Labels來過濾資源。
Selector通過-l引數來使用:
$ kubectl delete all -lapp=nginx
replicationcontrollers/my-nginx
replicationcontrollers/my-nginx
services/my-nginx-svc
因為kubectl會使用相同的語法將其接受的資源名稱再次輸出,所以通過$()或者xarg可以很容易地進行連續的操作:
$ kubectl get $(kubectl create -f ./nginx/ | grep my-nginx)
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
my-nginx nginx nginx app=nginx 2
NAME LABELS SELECTOR IP(S) PORT(S)
my-nginx-svc app=nginx app=nginx 10.0.152.174 80/TCP
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
my-nginx nginx nginx app=nginx 2
NAME LABELS SELECTOR IP(S) PORT(S)
my-nginx-svc app=nginx app=nginx 10.0.152.174 80/TCP
3、有效地使用Labels
目前為止我們使用的例子中,資源最多有一個Label。
下面介紹在資源集合之間使用多個Labels來進行區分。
例如,不同的應用使用了不同的label,app等於不同的值,但是一個多層的應用,例如guestbook
example
example
需要額外地區分不同層,那麼前端可以攜帶以下標籤:
labels:
app: guestbook
tier: frontend
而Redis主節點和從節點使用不同的tier標籤,同時甚至有可能會有一個role標籤:
labels:
app: guestbook
tier: backend
role: master
labels:
app: guestbook
tier: backend
role: slave
Labels允許我們可以將資源劃分成任意級別,然後根據這些劃分尺度進行互動:
$ kubectl create -f ./guestbook-fe.yaml -f ./redis-master.yaml -f ./redis-slave.yaml
replicationcontrollers/guestbook-fe
replicationcontrollers/guestbook-redis-master
replicationcontrollers/guestbook-redis-slave
$ kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestbook backend slave
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <n/a> <n/a>
my-nginx-o0ef1 1/1 Running 0 29m nginx <n/a> <n/a>
$ kubectl get pods -lapp=guestbook,role=slave
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
replicationcontrollers/guestbook-fe
replicationcontrollers/guestbook-redis-master
replicationcontrollers/guestbook-redis-slave
$ kubectl get pods -Lapp -Ltier -Lrole
NAME READY STATUS RESTARTS AGE APP TIER ROLE
guestbook-fe-4nlpb 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-fe-ght6d 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-fe-jpy62 1/1 Running 0 1m guestbook frontend <n/a>
guestbook-redis-master-5pg3b 1/1 Running 0 1m guestbook backend master
guestbook-redis-slave-2q2yf 1/1 Running 0 1m guestbook backend slave
guestbook-redis-slave-qgazl 1/1 Running 0 1m guestbook backend slave
my-nginx-divi2 1/1 Running 0 29m nginx <n/a> <n/a>
my-nginx-o0ef1 1/1 Running 0 29m nginx <n/a> <n/a>
$ kubectl get pods -lapp=guestbook,role=slave
NAME READY STATUS RESTARTS AGE
guestbook-redis-slave-2q2yf 1/1 Running 0 3m
guestbook-redis-slave-qgazl 1/1 Running 0 3m
4、多種部署
另外一個會使用到多標籤的場景是:分別部署一個元件的不同版本、不同配置。
將應用的新版本和舊版一同部署是十分正常的,這樣一來,在舊版本淘汰之前,新版應用可以接管舊版本的一些功能使用。
例如,一個新版的guestbook前端可以攜帶以下的標籤:
labels:
app: guestbook
tier: frontend
track: canary
同時,穩定版本的track標籤有不同的值,這樣一來,兩個RC控制的Pods集合就不會發生重疊:
labels:
app: guestbook
tier: frontend
track: stable
通過選擇它們Labels的子集,省略track這個Label,前端的Service可以跨越兩組replicas:
selector:
app: guestbook
tier: frontend
5、更新Labels
有時候,在建立新的資源之前,已存在的Pods或者其他資源需要重置Label。
這可以通過kubectl label來做到,例如:
$ kubectl label pods -lapp=nginx tier=fe
NAME READY STATUS RESTARTS AGE
my-nginx-v4-9gw19 1/1 Running 0 14m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-hayza 1/1 Running 0 13m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-mde6m 1/1 Running 0 17m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-sh6m8 1/1 Running 0 18m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-wfof4 1/1 Running 0 16m
$ kubectl get pods -lapp=nginx -Ltier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-v4-9gw19 1/1 Running 0 15m fe
my-nginx-v4-hayza 1/1 Running 0 14m fe
my-nginx-v4-mde6m 1/1 Running 0 18m fe
my-nginx-v4-sh6m8 1/1 Running 0 19m fe
my-nginx-v4-wfof4 1/1 Running 0 16m fe
NAME READY STATUS RESTARTS AGE
my-nginx-v4-9gw19 1/1 Running 0 14m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-hayza 1/1 Running 0 13m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-mde6m 1/1 Running 0 17m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-sh6m8 1/1 Running 0 18m
NAME READY STATUS RESTARTS AGE
my-nginx-v4-wfof4 1/1 Running 0 16m
$ kubectl get pods -lapp=nginx -Ltier
NAME READY STATUS RESTARTS AGE TIER
my-nginx-v4-9gw19 1/1 Running 0 15m fe
my-nginx-v4-hayza 1/1 Running 0 14m fe
my-nginx-v4-mde6m 1/1 Running 0 18m fe
my-nginx-v4-sh6m8 1/1 Running 0 19m fe
my-nginx-v4-wfof4 1/1 Running 0 16m fe
6、擴縮你的應用
當你的應用負載增加或者縮小了,通過kubectl可以十分簡單地進行擴縮。
例如,將nginx replicas的Pod數量由2增長到3:
$ kubectl scale rc my-nginx –replicas=3
scaled
$ kubectl get pods -lapp=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-1jgkf 1/1 Running 0 3m
my-nginx-divi2 1/1 Running 0 1h
my-nginx-o0ef1 1/1 Running 0 1h
scaled
$ kubectl get pods -lapp=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-1jgkf 1/1 Running 0 3m
my-nginx-divi2 1/1 Running 0 1h
my-nginx-o0ef1 1/1 Running 0 1h
7、保證服務不中斷的情況下更新你的應用
有時候,你需要更新你已經部署的應用,在上面的部署例子中,是通過一個新的Image或者Image tag來更新。
kubectl不同的更新操作方式,適用於各種不同的場景。
在保證服務不中斷的情況下,為了更新應用,kubectl提供了一個叫做“rolling
update”的操作,它是一次更新一個Pod,而不是在同一時間將所有服務停掉。
update”的操作,它是一次更新一個Pod,而不是在同一時間將所有服務停掉。
請檢視
和
來獲得更多資訊。
假設你執行著1.7.9版本的nginx:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx:1.7.9
ports:
– containerPort: 80
kind: ReplicationController
metadata:
name: my-nginx
spec:
replicas: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
– name: nginx
image: nginx:1.7.9
ports:
– containerPort: 80
為了將其升級到1.9.1,你可以使用kubectl rolling-update –image:
$ kubectl rolling-update my-nginx –image=nginx:1.9.1
Creating my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
Creating my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
開啟另外一個視窗,你可以看到kubectl為了將新的Pods和舊的區分開,為這些Pods新增了一個deployment標籤,值為配置的Hash值:
$ kubectl get pods -lapp=nginx -Ldeployment
NAME READY STATUS RESTARTS AGE DEPLOYMENT
my-nginx-1jgkf 1/1 Running 0 1h 2d1d7a8f682934a254002b56404b813e
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-k156z 1/1 Running 0 1m ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-v95yh 1/1 Running 0 35s ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-divi2 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-o0ef1 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-q6all 1/1 Running 0 8m 2d1d7a8f682934a254002b56404b813e
NAME READY STATUS RESTARTS AGE DEPLOYMENT
my-nginx-1jgkf 1/1 Running 0 1h 2d1d7a8f682934a254002b56404b813e
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-k156z 1/1 Running 0 1m ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-ccba8fbd8cc8160970f63f9a2696fc46-v95yh 1/1 Running 0 35s ccba8fbd8cc8160970f63f9a2696fc46
my-nginx-divi2 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-o0ef1 1/1 Running 0 2h 2d1d7a8f682934a254002b56404b813e
my-nginx-q6all 1/1 Running 0 8m 2d1d7a8f682934a254002b56404b813e
kubectl rolling-update會將進展過程報告出來:
Updating my-nginx replicas: 4, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 1
At end of loop: my-nginx replicas: 4, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 1
At beginning of loop: my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
Updating my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
At end of loop: my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
At beginning of loop: my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
Updating my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
At end of loop: my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
At beginning of loop: my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
Updating my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
At end of loop: my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
At beginning of loop: my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
Updating my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
At end of loop: my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
Update succeeded. Deleting old controller: my-nginx
Renaming my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 to my-nginx
At end of loop: my-nginx replicas: 4, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 1
At beginning of loop: my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
Updating my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
At end of loop: my-nginx replicas: 3, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 2
At beginning of loop: my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
Updating my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
At end of loop: my-nginx replicas: 2, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 3
At beginning of loop: my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
Updating my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
At end of loop: my-nginx replicas: 1, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 4
At beginning of loop: my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
Updating my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
At end of loop: my-nginx replicas: 0, my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 replicas: 5
Update succeeded. Deleting old controller: my-nginx
Renaming my-nginx-ccba8fbd8cc8160970f63f9a2696fc46 to my-nginx
my-nginx
如果你中途遇到錯誤,可以使用–rollback引數來終止rolling update並恢復到以前的版本:
$ kubectl kubectl rolling-update my-nginx –image=nginx:1.9.1 –rollback
Found existing update in progress (my-nginx-ccba8fbd8cc8160970f63f9a2696fc46), resuming.
Found desired replicas.Continuing update with existing controller my-nginx.
Stopping my-nginx-02ca3e87d8685813dbe1f8c164a46f02 replicas: 1 -> 0
Update succeeded. Deleting my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
Found existing update in progress (my-nginx-ccba8fbd8cc8160970f63f9a2696fc46), resuming.
Found desired replicas.Continuing update with existing controller my-nginx.
Stopping my-nginx-02ca3e87d8685813dbe1f8c164a46f02 replicas: 1 -> 0
Update succeeded. Deleting my-nginx-ccba8fbd8cc8160970f63f9a2696fc46
my-nginx
不變的容器是最好的,可以通過這個例子來保持容器不變。
如果你想更新的不僅僅是映象(如,命令引數和環境變數),你可以用一個新的name和label來建立一個新的RC:
apiVersion: v1
kind: ReplicationController
metadata:
name: my-nginx-v4
spec:
replicas: 5
selector:
app: nginx
deployment: v4
template:
metadata:
labels:
app: nginx
deployment: v4
spec:
containers:
– name: nginx
image: nginx:1.9.2
args: [“nginx”,”-T”]
ports:
kind: ReplicationController
metadata:
name: my-nginx-v4
spec:
replicas: 5
selector:
app: nginx
deployment: v4
template:
metadata:
labels:
app: nginx
deployment: v4
spec:
containers:
– name: nginx
image: nginx:1.9.2
args: [“nginx”,”-T”]
ports:
– containerPort: 80
然後將原本的Pod更新到新版:
$ kubectl rolling-update my-nginx -f ./nginx-rc.yaml
Creating my-nginx-v4
At beginning of loop: my-nginx replicas: 4, my-nginx-v4 replicas: 1
Updating my-nginx replicas: 4, my-nginx-v4 replicas: 1
At end of loop: my-nginx replicas: 4, my-nginx-v4 replicas: 1
At beginning of loop: my-nginx replicas: 3, my-nginx-v4 replicas: 2
Updating my-nginx replicas: 3, my-nginx-v4 replicas: 2
At end of loop: my-nginx replicas: 3, my-nginx-v4 replicas: 2
At beginning of loop: my-nginx replicas: 2, my-nginx-v4 replicas: 3
Updating my-nginx replicas: 2, my-nginx-v4 replicas: 3
At end of loop: my-nginx replicas: 2, my-nginx-v4 replicas: 3
At beginning of loop: my-nginx replicas: 1, my-nginx-v4 replicas: 4
Updating my-nginx replicas: 1, my-nginx-v4 replicas: 4
At end of loop: my-nginx replicas: 1, my-nginx-v4 replicas: 4
At beginning of loop: my-nginx replicas: 0, my-nginx-v4 replicas: 5
Updating my-nginx replicas: 0, my-nginx-v4 replicas: 5
At end of loop: my-nginx replicas: 0, my-nginx-v4 replicas: 5
Update succeeded. Deleting my-nginx
my-nginx-v4
Creating my-nginx-v4
At beginning of loop: my-nginx replicas: 4, my-nginx-v4 replicas: 1
Updating my-nginx replicas: 4, my-nginx-v4 replicas: 1
At end of loop: my-nginx replicas: 4, my-nginx-v4 replicas: 1
At beginning of loop: my-nginx replicas: 3, my-nginx-v4 replicas: 2
Updating my-nginx replicas: 3, my-nginx-v4 replicas: 2
At end of loop: my-nginx replicas: 3, my-nginx-v4 replicas: 2
At beginning of loop: my-nginx replicas: 2, my-nginx-v4 replicas: 3
Updating my-nginx replicas: 2, my-nginx-v4 replicas: 3
At end of loop: my-nginx replicas: 2, my-nginx-v4 replicas: 3
At beginning of loop: my-nginx replicas: 1, my-nginx-v4 replicas: 4
Updating my-nginx replicas: 1, my-nginx-v4 replicas: 4
At end of loop: my-nginx replicas: 1, my-nginx-v4 replicas: 4
At beginning of loop: my-nginx replicas: 0, my-nginx-v4 replicas: 5
Updating my-nginx replicas: 0, my-nginx-v4 replicas: 5
At end of loop: my-nginx replicas: 0, my-nginx-v4 replicas: 5
Update succeeded. Deleting my-nginx
my-nginx-v4
你也可以通過update
demo來檢視一個視覺化的rolling update程式。
demo來檢視一個視覺化的rolling update程式。
8、就地更新資源
有時候,對你建立的資源進行一些小的、無干擾的更新是必要的。
例如你可能想為你的Object新增描述資訊,annotation。
通過kubectl patch命令可以很輕鬆的做到:
$ kubectl patch rc my-nginx-v4 -p `{“metadata”: {“annotations”: {“description”: “my frontend running nginx”}}}`
my-nginx-v4
$ kubectl get rc my-nginx-v4 -o yaml
apiVersion: v1
kind: ReplicationController
metadata:
annotations:
description: my frontend running nginx
…
my-nginx-v4
$ kubectl get rc my-nginx-v4 -o yaml
apiVersion: v1
kind: ReplicationController
metadata:
annotations:
description: my frontend running nginx
…
這個patch使用JSON格式來定義的。
對於一些更重要的更新,你可以使用get命令檢視資源,編輯之後使用replace命令來更新資源並帶有版本號:
$ kubectl get rc my-nginx-v4 -o yaml > /tmp/nginx.yaml
$ vi /tmp/nginx.yaml
$ kubectl replace -f /tmp/nginx.yaml
replicationcontrollers/my-nginx-v4
$ rm $TMP
$ vi /tmp/nginx.yaml
$ kubectl replace -f /tmp/nginx.yaml
replicationcontrollers/my-nginx-v4
$ rm $TMP
系統通過確認當前resourceVersion和你所做編輯的版本是不一樣的,來確保你不會破壞別的使用者或者元件所做的更新。
如果你想不顧一切地更新,在編輯的時候將resourceVersion移除。
但是,如果你想這麼做,不要使用你的原始配置檔案作為更新源,因為追加的欄位最好是在資源處於活動狀態時設定。
9、暫時性的更新
在有些情況下,你可能需要更新一些不能一次就初始化完畢的資源,或者你可能只想要做完更改之後馬上恢復原樣。
例如修復一些RC建立的不可用的Pods,可以通過replace –force刪除和重新建立資源來做到這些。
假設這樣子的話,你可以簡單的修改你的原始配置檔案:
$ kubectl replace -f ./nginx-rc.yaml –force
replicationcontrollers/my-nginx-v4
replicationcontrollers/my-nginx-v4
replicationcontrollers/my-nginx-v4
replicationcontrollers/my-nginx-v4
相關文章
- 在生產環境使用Docker部署應用Docker
- Java列舉類在生產環境中的使用方式Java
- 如何建立 Angular library 並在生產環境中消費Angular
- GPU 環境搭建指南:使用 GPU Operator 加速 Kubernetes GPU 環境搭建GPU
- 傲視Kubernetes(三):Kubernetes中的Pod
- GitLab Runner部署(kubernetes環境)Gitlab
- ForkJoinPool在生產環境中使用遇到的一個問題
- 如何一步步在生產環境上部署django和vueDjangoVue
- 【機器學習】在生產環境使用Kafka構建和部署大規模機器學習機器學習Kafka
- 在生產中執行kubernetes上的Istio
- 在生產環境中使用預寫日誌WAL的SQLite - victoriaSQLite
- Kubernetes部署單元-Pod
- 如何使用Kubernetes的configmap通過環境變數注入到pod裡變數
- 你還在生產環境改程式碼麼?函式計算版本管理(三)使用別名進行灰度釋出函式
- JeecgBoot 如何在生產環境關閉 Swagger 文件bootSwagger
- 使用 TensorFlow Extended (TFX) 在生產環境中部署機器學習 丨 Google 開發者大會 2018機器學習Go
- kubernetes環境部署單節點redisRedis
- Kubernetes之Pod工作負載負載
- ClickHouse生產環境部署
- 在生產中執行Elasticsearch的深入指南 – TechNotesElasticsearch
- 單例模式在生產環境jedis叢集中的應用單例模式
- 使用 kind 快速搭建 kubernetes 環境
- 如何在 Kubernetes 環境中搭建 MySQL(四):使用 StMySql
- 在生產環境中除錯 Angular 應用程式而不顯示源對映除錯Angular
- 使用dockerfile 部署lnmpr環境DockerLNMP
- 【Swagger】2.不在生產環境暴露,可以修改預設地址Swagger
- kubernetes之pod中斷
- 專案開發中,如何使用eolinker進行環境管理:開發、測試和生產環境
- 玩轉伺服器之環境篇:PHP和Python環境部署指南伺服器PHPPython
- OpenFaaS的Kubernetes 部署指南
- linux伺服器環境部署(三、docker部署nginx)Linux伺服器DockerNginx
- 生產環境的 ElasticSearch 安裝指南Elasticsearch
- 雲端設計平臺Coohom在生產環境中使用istio的經驗與實踐
- Kubernetes環境搭建
- Mac環境下安裝PodMac
- Flask 生產環境部署(Falsk + uWSGI + nginx)FlaskNginx
- vue-element-admin部署生產環境Vue
- 使用 Kubernetes 來部署你的 Laravel 程式Laravel
- 在生產中部署 ES2015+ 程式碼