K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)

因爲K8s技術的火爆,致使如今大大小小的企業都在使用,雖然沒有普及,但本人相信時早晚的事情,因此抓緊時間多學習一下吧!html

在K8s中建立資源的方式有兩種:命令行和YAML文件,本次博文主要介紹使用YAML文件的方式,如需使用命令行建立資源請參考K8s資源對象的基本管理node

Kubernetes中的YAML文件與配置清單是同樣的,根據我的習慣。本次博文統稱爲YAML文件!linux

1、YAML文件基礎

YAML是專門用來配置文件的語言,很是簡潔和強大。與瞭解的properties、XML、json等數據格式,習慣以後就會發現愈來愈好用。其實YAML就是結合了大部分的標記語言的特性,整合新開發的。nginx

YAML文件的特色:web

  • 井井有條、結構清晰;
  • 使用簡單、上手容易;
  • 功能強大、語義豐富;
    須要特別注意的是:
  • 大小寫敏感;
  • 嚴格要求縮進;

2、YAML文件使用

1)YAML文件的組成

Kubernetes中的YAML文件主要由五個一級字段組成,分別是:docker

  • apiVersion:api版本信息;
  • kind:指定建立資源對象的類型;
  • metadata:元數據內部的嵌套字段,定義了資源對象的名稱、名稱空間等;
  • spec:規範定義資源應該擁有什麼樣的特性,依靠控制器確保性能能夠知足,知足用戶指望的狀態。
  • status:顯示資源的當前狀態,K8s就是確保當前狀態向目標狀態無限靠近從而知足用戶指望。表明資源當前的狀態;

2)獲取編寫YAML文件的幫助

雖然知道了YAML文件中的一級字段都是什麼,可是仍是不知道應該怎麼寫。能夠藉助如下命令來獲取一些幫助信息。json

[root@master ~]# kubectl api-versions           
//獲取當前集羣支持的 apiserver版本
[root@master ~]# kubectl api-resources 
//獲取所有的api資源對象
[root@master ~]# kubectl explain deployment
//查看k8s某個對象的配置清單格式,應該包含哪些字段及使用方法
[root@master ~]# kubectl explain deployment.spec
//這個命令是很是重要的,它能夠一級一級來獲取幫助

3)YAML文件的基本格式

[root@master ~]# cat web.yaml 
kind: Deployment                    //指定要建立的資源對象
apiVersion: extensions/v1beta1        //指定deployment所對應的API版本信息
metadata:
  name: web                  //定義deployment的名稱
spec:
  replicas: 2                  //指定副本數量
  template:
    metadata:
      labels:                        //指定pod的標籤
        app: web_server
    spec:
      containers:
      - name: nginx           //指定pod運行的容器的名稱
        image: nginx          //指定運行容器所需的鏡像

4)apply建立或更新

[root@master ~]# kubectl apply -f web.yaml
//使用「-f」來指定yaml文件,根據yaml文件中定義的內容生成所需的資源

apply能夠指定屢次,若是發現文件不一樣,則更新vim

5)delete刪除

[root@master ~]# kubectl delete -f web.yaml
//刪除yaml文件中定義的資源

6)驗證

[root@master ~]# kubectl get deployments. web
//查看web控制器所產生的pod
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web    2/2     2            2           5m50s
[root@master ~]# kubectl describe deployments. web
//查看web控制器的詳細信息

返回的結果以下:
K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)後端

這樣一來,Kubernetes已經根據YAML文件生成了咱們所需的pod資源!api

[root@master ~]# kubectl get pod -o wide          //查看pod的詳細信息
NAME                  READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
web-d6ff6c799-7jtvd   1/1     Running   0          17m   10.244.2.2   node02   <none>           <none>
web-d6ff6c799-7tpdc   1/1     Running   0          17m   10.244.1.2   node01   <none>           <none>

K8s集羣內部測試訪問:
K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)

3、建立YAML文件使K8s中pod的服務可以被外部訪問

[root@master ~]# cat web-svc.yaml 
kind: Service
apiVersion: v1
metadata:
  name: web-svc
spec:
  type: NodePort           //指定類型爲NodePort,可讓外部訪問,不然默認狀況下是cluster IP,僅限集羣內部訪問
  selector:        
    app: web_server             //必須與deployment資源對象的標籤進行關聯
  ports:
  - protocol: TCP
    port: 80                          //指定要映射到的Cluster  IP的端口
    targetPort: 80                //指定的是要映射pod中的端口
    nodePort: 31000           //指定映射到宿主機的端口,範圍是30000~32767
[root@master ~]# kubectl apply -f web-svc.yaml 
//生成service的控制文件(yaml中已經定義其名稱爲web-svc)
[root@master ~]# kubectl get svc web-svc     //查看service控制器
NAME      TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
web-svc   NodePort   10.99.32.22   <none>        80:31000/TCP   12m
//TYPE:爲NodePort,可使外部訪問;
//PORT:映射出的端口與咱們定義的同樣

測試訪問:
K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)

注意:是訪問羣集中任意節點均可以訪問k8s集羣中pod所提供的服務!

4、底層負載均衡實現原理

[root@master ~]# kubectl describe svc web-svc 
//查看service的詳細信息

返回的信息以下:
K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)
既然說到,Endpoints指定的是後端pod的IP地址,那麼下面進行驗證:

[root@master ~]# kubectl get pod -o wide | awk '{print $6}'
//提取後端pod的IP地址
IP
10.244.2.2
10.244.1.2
//與上述查詢的結果同樣!

咱們知道service是有負載均衡的能力,那麼是怎麼實現的?

其實,背後的原理並無那麼高大上,kube-proxy經過iptables的轉發機制來實現負載均衡的效果的,先定義目標IP是service提供的羣集IP,而後使用「-j」選項轉發到其餘iptables規則,接下來驗證一下:

[root@master ~]# kubectl get svc web-svc | awk '{print $3}'
//首先查看service的羣集IP地址
CLUSTER-IP
10.99.32.22
[root@master ~]# iptables-save | grep 10.99.32.22
//查看iptables規則中與羣集IP地址相關的內容
-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
從上述結果中能夠看出,當目標地址是羣集IP時,就會轉發到KUBE-SVC-3RBUQ3B6P3MTQ3S7規則中
[root@master ~]# iptables-save | grep KUBE-SVC-3RBUQ3B6P3MTQ3S7
:KUBE-SVC-3RBUQ3B6P3MTQ3S7 - [0:0]
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/web-svc:" -m tcp --dport 31000 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
-A KUBE-SERVICES -d 10.99.32.22/32 -p tcp -m comment --comment "default/web-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-3RBUQ3B6P3MTQ3S7
-A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-E3SP5QDRAUFB55IC
-A KUBE-SVC-3RBUQ3B6P3MTQ3S7 -j KUBE-SEP-3T3LUFAKMOTS5BKN
//從查詢結果中能夠看出其負載均衡的效果,由於後端只建立了兩個pod,因此其機率爲0.5

由此能夠看出service實現負載均衡的效果:默認狀況下使用iptables規則,固然還可使用其餘的方法,這裏就不介紹了!

查看負載均衡的詳細信息需根據cluster ip爲切入口!

實現負載均衡最根本的原理就是:iptables規則根據random(隨機數)實現的負載均衡!

5、服務回滾到指定的版本

經過K8s資源對象的基本管理之使用命令行的方式能夠了解到kubernetes版本升級、回滾的操做與docker swarm幾乎是同樣的。回滾操做只能回滾到上一個版本。

搭建私有倉庫,使用鏡像製做自定義鏡像(三個版本),根據主頁內容進行區分,將自定義鏡像上傳到私有倉庫中,因爲過於簡單,過程略……

kubernetes還能夠回滾到指定的版本,方法以下:

[root@master yaml]# cat httpd01.deployment.yaml 
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: httpd
spec:
  revisionHistoryLimit: 10                              //記錄歷史版本信息爲10個
  replicas: 3
  template:
    metadata:
      labels:
        app: httpd-server
    spec:
      containers:
      - name: httpd
        image: 192.168.1.1:5000/httpd:v1                   //三個版本根據鏡像進行區分
        ports:                                                         //這個只是一個聲名沒有任何做用
        - containerPort: 80
[root@master yaml]# cat httpd02.deployment.yaml 
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: httpd
spec:
  revisionHistoryLimit: 10
  replicas: 3
  template:
    metadata:
      labels:
        app: httpd-server
    spec:
      containers:
      - name: httpd
        image: 192.168.1.1:5000/httpd:v2                   //三個版本根據鏡像進行區分
        ports:
        - containerPort: 80
[root@master yaml]# cat httpd03.deployment.yaml 
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: httpd
spec:
  revisionHistoryLimit: 10
  replicas: 3
  template:
    metadata:
      labels:
        app: httpd-server
    spec:
      containers:
      - name: httpd
        image: 192.168.1.1:5000/httpd:v3                   //三個版本根據鏡像進行區分
        ports:
        - containerPort: 80
[root@master yaml]# kubectl apply -f httpd01.deployment.yaml --record
//--record的做用就是記錄歷史版本信息
[root@master yaml]# kubectl rollout history deployment httpd
//查看歷史的版本信息
deployment.extensions/httpd 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=httpd01.deployment.yaml --record=true
//1,表示版本對應的編號,也能夠看出其對應的yaml
[root@master yaml]# kubectl apply -f httpd02.deployment.yaml --record
[root@master yaml]# kubectl apply -f httpd03.deployment.yaml --record
//根據yaml文件進行兩次升級
[root@master yaml]# kubectl rollout history deployment httpd 
deployment.extensions/httpd 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=httpd01.deployment.yaml --record=true
2         kubectl apply --filename=httpd02.deployment.yaml --record=true
3         kubectl apply --filename=httpd03.deployment.yaml --record=true
//確認升級的版本信息已經記錄
[root@master yaml]# vim httpd-svc.yaml
kind: Service
apiVersion: v1
metadata:
  name: httpd-svc
spec:
  type: NodePort
  selector:
    app: httpd-server
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 31000
[root@master yaml]# kubectl apply -f httpd-svc.yaml
//建立一個svc便於訪問測試
[root@master yaml]# curl 127.0.0.1:31000 
<h1>hello lvzhenjiang:v3</h1>
 //訪問測試頁面效果
[root@master yaml]# kubectl  rollout undo deployment httpd  --to-revision=1
//回滾到版本1,使用--to-revision=1表示,1表示查看歷史版本的第一列編號
[root@master yaml]# curl 127.0.0.1:31000      //測試訪問
<h1>hello lvzhenjiang:v1</h1>

6、用label控制pod的位置

若是不指定pod的位置的話,默認狀況下,是由K8s中scheduler這個組件來完成的,不能人爲的干預。若是是業務須要手動指定的話,那麼就須要如下方法:

[root@master yaml]# kubectl label nodes node02 disk=ssd
//手動給node02打上一個 disk=ssd的標籤
[root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd
//查看集羣中各個節點的標籤(包含disk=ssd)
node02   Ready    <none>   5d22h   v1.15.0   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node02,kubernetes.io/os=linux
//從結果中能夠可看出只有node02包含這個標籤
[root@master yaml]# vim httpd.yaml
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: httpd
spec:
  revisionHistoryLimit: 10
  replicas: 3
  template:
    metadata:
      labels:
        app: httpd-server
    spec:
      containers:
      - name: httpd
        image: 192.168.1.1:5000/httpd:v1
        ports:
        - containerPort: 80
      nodeSelector:                //指定標籤選擇器
        disk: ssd 
[root@master yaml]# kubectl apply -f httpd.yaml 
//根據yaml文件生成所需的pod資源
[root@master yaml]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
httpd-5895f5548b-6lb97   1/1     Running   0          12s   10.244.2.8    node02   <none>           <none>
httpd-5895f5548b-gh8br   1/1     Running   0          10s   10.244.2.10   node02   <none>           <none>
httpd-5895f5548b-llxh7   1/1     Running   0          12s   10.244.2.9    node02   <none>           <none>
//從查詢結果中能夠看出三個pod資源都運行在node02節點上

上述需求已經實現,可是隻要有人爲干預的地方就會錯誤的產生,不得不考慮如下這種狀況!假若將node02的標籤進行刪除的話,看一下會發生什麼狀況!

[root@master yaml]# kubectl label nodes node02 disk-
//將node02的disk=ssd的標籤進行刪除
[root@master yaml]# kubectl get nodes --show-labels | grep disk=ssd
//驗證,標籤已經被刪除
[root@master yaml]# kubectl delete -f httpd.yaml 
//將本來的pod資源進行刪除
[root@master yaml]# kubectl apply -f httpd.yaml 
//從新生成pod資源(yaml文件中依然指定了標籤)
[root@master yaml]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
httpd-5895f5548b-7w26q   0/1     Pending   0          65s   <none>   <none>   <none>           <none>
httpd-5895f5548b-c6p6s   0/1     Pending   0          65s   <none>   <none>   <none>           <none>
httpd-5895f5548b-v4s5c   0/1     Pending   0          65s   <none>   <none>   <none>           <none>
//可是查看pod的狀態爲Pending,顯然這種狀態的pod是不正常的

即便標籤的不存在的,yaml文件中也指定了標籤,建立pod資源時,不會出現錯誤,可是pod的狀態爲Pending(等待的狀態),解決方法以下:

[root@master yaml]# kubectl describe pod httpd-5895f5548b-7w26q
//查看pod的詳細信息

返回的結果以下:
K8s資源對象的基本管理之使用YAML文件的方式(升級、回滾、擴容、縮容)

從結果中就已經看出了是由於標籤選擇器與集羣中node的標籤不匹配致使的!

若是以上沒有發現錯誤的信息,還需進行如下操做:

[root@master yaml]# kubectl logs -n kube-system kube-scheduler-master
//查看你scheduler組件所產生的日誌信息
[root@master yaml]# less /var/log/messages | grep kubelet
//查看系統日誌中包含kubelet組件的信息
//由於kubelet是負責管理pod的

有關K8s的詳細介紹仍是建議參考K8s中文文檔

————————本文到此爲止,感謝閱讀————————

相關文章
相關標籤/搜索