Kubernetes 學習總結(3) M

APIserver符合RESTful風格,支援GET/PUT/DELETE/POST等各種操作。所以也支援kubectl通過一系列命令對各處資源進行管理控制。 常用的資源 1)、workLoad(工作負載型資源,運行APP,對外提供服務): Pod/ReplicaSet/Deployment/ StatefulSet/ DaemonSet/ Job/ Cronjob / 2)、service discovery and Load Balance(服務發現及均衡型資源):Service/ Ingress 3)、configuration and storage(配置與存儲類型資源) :Volume,CSI(容器存儲介面,擴展第三方的存儲) ConfigMap,Secret(特殊的配置類型資源) Downward API(配置類型資源) 4)、集群級資源(配置在名稱空間級別): namespace, node, role, clusterRole, roleBinding, clusterRoleBinding 5)、元數據類型資源:HPA、PodTemplate、limitRange(讀取許可權)

一、配置清單(configuration mainfest) kubectl 通常通過ymal格式的配置清單對資源進行管理控制。APIserver僅處理Json格式定義的資源定義。ymal格式的配置清單由APIserver自動將其轉為json格式,而後再提交處理。 [root@docker79 ~]# kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deploy 2 2 2 2 1d [root@docker79 ~]# kubectl get deployment nginx-deploy -o yaml (查看nginx-deploy的配置清單) 配置清單主格式如下 apiVersion: group/version (如果group省略表示core組) kind: Pod (資源類型) metadata: 元數據 spec: 期望狀態 disired state status: 當前狀態, current state ,本欄位由kubernetes 集群維護;

[root@docker79 ~]# kubectl api-versions (查看默認支援的group與version)

admissionregistration.k8s.io/v1beta1  apiextensions.k8s.io/v1beta1  apiregistration.k8s.io/v1  apiregistration.k8s.io/v1beta1  apps/v1  apps/v1beta1  apps/v1beta2  authentication.k8s.io/v1  authentication.k8s.io/v1beta1  authorization.k8s.io/v1  authorization.k8s.io/v1beta1  autoscaling/v1  autoscaling/v2beta1  batch/v1  batch/v1beta1  certificates.k8s.io/v1beta1  events.k8s.io/v1beta1  extensions/v1beta1  networking.k8s.io/v1  policy/v1beta1  rbac.authorization.k8s.io/v1  rbac.authorization.k8s.io/v1beta1  scheduling.k8s.io/v1beta1  storage.k8s.io/v1  storage.k8s.io/v1beta1  v1

[root@docker79 ~]#

kubectl explain kubectl explain Resource_Kind[.Subitem…] 查看相關resource 在定義配置清單時的幫助資訊。在幫助資訊中常見格式如下: apiVersion <string> 表示字元串類型 metadata <Object> 表示需要嵌套多層欄位 labels <map[string]string> 表示由k:v組成的映射 finalizers <[]string> 表示字串列表 ownerReferences <[]Object> 表示對象列表

資源清單 例1: [root@docker79 ~]# mkdir manifests [root@docker79 ~]# cd manifests/ [root@docker79 manifests]# vim pod-demo.yaml [root@docker79 manifests]# cat pod-demo.yaml

apiVersion: v1  kind: Pod  metadata:    name: pod-demo    namespace: default    labels:      app: nginx      tier: frontend  spec:    containers:    - name: nginx      image: nginx:1-alpine    - name: busybox      image: busybox:latest      command:      - "/bin/sh"      - "-c"      - "sleep 3600"

[root@docker79 manifests]# kubectl create -f pod-demo.yaml pod/pod-demo created [root@docker79 manifests]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-demo 2/2 Running 0 8s [root@docker79 manifests]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE pod-demo 2/2 Running 0 17s 10.244.1.9 docker78 <none> [root@docker79 manifests]# [root@docker79 manifests]# kubectl logs pod-demo busybox [root@docker79 manifests]# kubectl logs pod-demo nginx [root@docker79 manifests]# kubectl exec -it pod-demo -c busybox — /bin/sh / # netstat -tnlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN – / # exit [root@docker79 manifests]# kubectl delete -f pod-demo.yaml pod "pod-demo" deleted [root@docker79 manifests]#

再次修改資源清單,例2: [root@docker79 manifests]# vim pod-demo.yaml [root@docker79 manifests]# cat pod-demo.yaml

apiVersion: v1  kind: Pod  metadata:    name: pod-demo    namespace: default    labels:      app: nginx      tier: frontend  spec:    containers:    - name: nginx      image: nginx:1-alpine      imagePullPolicy: IfNotPresent      ports:      - containerPort: 80        name: http      - name: https        containerPort: 443

[root@docker79 manifests]# kubectl apply -f pod-demo.yaml pod/pod-demo created [root@docker79 manifests]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-demo 1/1 Running 0 6s [root@docker79 manifests]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE pod-demo 1/1 Running 0 14s 10.244.1.10 docker78 <none> [root@docker79 manifests]# 說明:imagePullPolicy: <string> 有三個值,分別是 Always ,Never,IfNotPresent (如果標籤是latest,默認策略為Always) ,一項創建本項不能更新。 ports 選項可參考:kubectl explain pod.spec.containers.ports

二、Labels、Selector及 Annotation Lables 是 key=value 格式的鍵值對兒。key最大長度 63字元,只能以字母或數字開頭,由字母、數字、-、_、. 組成。value 最大長度 63字元,可以為空。標籤支援前綴,但不能超出253字元(一般都是name或FQDN) [root@docker79 manifests]# kubectl get pods –show-labels NAME READY STATUS RESTARTS AGE LABELS pod-demo 1/1 Running 0 14m app=nginx,tier=frontend [root@docker79 manifests]# kubectl get pods -L app NAME READY STATUS RESTARTS AGE APP pod-demo 1/1 Running 0 15m nginx [root@docker79 manifests]# kubectl get pods -l app –show-labels NAME READY STATUS RESTARTS AGE LABELS pod-demo 1/1 Running 0 15m app=nginx,tier=frontend [root@docker79 manifests]# kubectl label pods pod-demo release=canary 手工打標籤 pod/pod-demo labeled [root@docker79 manifests]# kubectl get pods –show-labels NAME READY STATUS RESTARTS AGE LABELS pod-demo 1/1 Running 0 24m app=nginx,release=canary,tier=frontend [root@docker79 manifests]# kubectl label pods pod-demo release=canary2 –overwrite pod/pod-demo labeled [root@docker79 manifests]# kubectl get pods –show-labels NAME READY STATUS RESTARTS AGE LABELS pod-demo 1/1 Running 0 25m app=nginx,release=canary2,tier=frontend [root@docker79 manifests]#

Selector標籤選擇器 支援兩類:1、等值關係的標籤選擇器 ; 2、集合關係的標籤選擇器。 等值關係: = , == , != 集合關係: in , notin [root@docker79 manifests]# kubectl get pods -l "release in (canary,beta,alpha)" NAME READY STATUS RESTARTS AGE pod-demo 1/1 Running 0 28m [root@docker79 manifests]#

標籤選擇器關聯其它資源(如pod控制器和service) 。使用以下兩個欄位進行關聯: matchLabels: 直接給定鍵值 matchExpressions: 基於給定的表達式來定義使用標籤選擇器 ,定義格式如 { key: "KEY", operator: "OPERATER", value: [ VAL1, VAL2, …]} 操作符: In , NotIn (values欄位的值必須為非空列表) Exists , NotExists(values欄位的值必須為空列表)

節點標籤選擇器 nodeSelector <map[string]string> 例:

[root@docker79 manifests]# kubectl get nodes --show-labels  NAME       STATUS    ROLES     AGE       VERSION   LABELS  docker77   Ready     <none>    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=docker77  docker78   Ready     <none>    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=docker78  docker79   Ready     master    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=docker79,node-role.kubernetes.io/master=  [root@docker79 manifests]#  [root@docker79 manifests]# kubectl label node docker77 diskType=ssd  node/docker77 labeled  [root@docker79 manifests]# kubectl get nodes --show-labels  NAME       STATUS    ROLES     AGE       VERSION   LABELS  docker77   Ready     <none>    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,diskType=ssd,kubernetes.io/hostname=docker77  docker78   Ready     <none>    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=docker78  docker79   Ready     master    2d        v1.11.2   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/hostname=docker79,node-role.kubernetes.io/master=  [root@docker79 manifests]#  [root@docker79 manifests]# kubectl delete -f pod-demo.yaml  pod "pod-demo" deleted  [root@docker79 manifests]# vim pod-demo.yaml  [root@docker79 manifests]# cat pod-demo.yaml  apiVersion: v1  kind: Pod  metadata:    name: pod-demo    namespace: default    labels:      app: nginx      tier: frontend  spec:    containers:    - name: nginx      image: nginx:1-alpine      imagePullPolicy: IfNotPresent      ports:      - containerPort: 80        name: http      - name: https        containerPort: 443    nodeSelector:      diskType: ssd  [root@docker79 manifests]#  [root@docker79 manifests]# kubectl apply -f pod-demo.yaml  pod/pod-demo created  [root@docker79 manifests]# kubectl get pods -o wide  NAME       READY     STATUS              RESTARTS   AGE       IP        NODE       NOMINATED NODE  pod-demo   0/1       ContainerCreating   0          17s       <none>    docker77   <none>  [root@docker79 manifests]#

annotations (資源註解) 與label不同之處在於: 它不能用於挑選資源對象,僅用於為對象提供「元數據」。 例:

[root@docker79 manifests]# kubectl delete -f pod-demo.yaml  pod "pod-demo" deleted  [root@docker79 manifests]# vim pod-demo.yaml  [root@docker79 manifests]# cat pod-demo.yaml  apiVersion: v1  kind: Pod  metadata:    name: pod-demo    namespace: default    labels:      app: nginx      tier: frontend    annotations:      inspiry.cn/author: "cluster admin"  spec:    containers:    - name: nginx      image: nginx:1-alpine      imagePullPolicy: IfNotPresent      ports:      - containerPort: 80        name: http      - name: https        containerPort: 443    nodeSelector:      diskType: ssd  [root@docker79 manifests]# kubectl apply -f pod-demo.yaml  pod/pod-demo created  [root@docker79 manifests]# kubectl get pods -o wide  NAME       READY     STATUS    RESTARTS   AGE       IP           NODE       NOMINATED NODE  pod-demo   1/1       Running   0          13s       10.244.2.9   docker77   <none>  [root@docker79 manifests]# kubectl describe pod pod-demo  Name:               pod-demo  Namespace:          default  Priority:           0  PriorityClassName:  <none>  Node:               docker77/192.168.20.77  Start Time:         Wed, 26 Sep 2018 16:25:44 +0800  Labels:             app=nginx                      tier=frontend  Annotations:        inspiry.cn/author=cluster admin     ......

三、pod生命周期 狀態: Pending , Running ,Failed, Successded , Unknown Pod生命周期中的重要行為: 1) 初始化container 2) container探測:liveness probe(存活探測) 和 readiness probe (就緒探測) 以上兩種探測使用的探針類型有:ExeAction、TCPSocketAction、HTTPGetAction 探針探測時的常用選項如下: failureThreshold 探測多少次宣告失敗,默認3次 periodSeconds 每次間隔時長,默認10s timeoutSeconds 每次的超時時長,默認1s initialDelaySeconds 初始延時的時長,默認立即探測 探測結果的重啟策略restartPolicy 有以下三種值: Always: 一旦故障,立即重啟 Never: 不重啟 OnFailure: 只有出現 failure狀態時才重啟 3) 啟動後勾子和中止前勾子 lifecycle kubectl explain pods.spec.containers.lifecycle.postStart kubectl explain pods.spec.containers.lifecycle.preStop

例1-liveness:

[root@docker79 manifests]# vim liveness-exec.yaml  [root@docker79 manifests]# cat liveness-exec.yaml  apiVersion: v1  kind: Pod  metadata:    name: liveness-exec-pod    namespace: default  spec:    containers:    - name: liveness-exec-container      image: busybox:latest      imagePullPolicy: IfNotPresent      command: ["/bin/sh", "-c", "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 3600" ]      livenessProbe:        exec:          command: ["test", "-e" , "/tmp/health"]        initialDelaySeconds: 1        periodSeconds: 3    restartPolicy: Never  [root@docker79 manifests]# kubectl apply -f liveness-exec.yaml  pod/liveness-exec-pod created  [root@docker79 manifests]# kubectl get pods  NAME                READY     STATUS    RESTARTS   AGE  liveness-exec-pod   1/1       Running   0          6s  pod-demo            1/1       Running   0          18m  [root@docker79 manifests]# kubectl get pods  NAME                READY     STATUS    RESTARTS   AGE  liveness-exec-pod   0/1       Error     0          51s  pod-demo            1/1       Running   0          19m  [root@docker79 manifests]#

說明:container啟動之後在30s之內 成功探測/tmp/health 文件存在,所以container status處於running狀態;但30s之後/tmp/health文件被rm,導致探測/tmp/health文件不存在,所以container status處於Eroor 。

例2-liveness:

 [root@docker79 manifests]# vim liveness-httpsocket.yaml  [root@docker79 manifests]# cat liveness-httpsocket.yaml  apiVersion: v1  kind: Pod  metadata:    name: liveness-httpget-pod    namespace: default  spec:    containers:    - name: liveness-httpget-container      image: nginx:1-alpine      imagePullPolicy: IfNotPresent      ports:      - name: http        containerPort: 80      livenessProbe:        httpGet:          port: http          path: /index.html        initialDelaySeconds: 1        periodSeconds: 3  [root@docker79 manifests]# kubectl apply -f liveness-httpsocket.yaml  pod/liveness-httpget-pod created  [root@docker79 manifests]# kubectl get pods -o wide  NAME                   READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  liveness-httpget-pod   1/1       Running   0          8s        10.244.1.13   docker78   <none>  pod-demo               1/1       Running   0          2h        10.244.2.9    docker77   <none>  [root@docker79 manifests]#  [root@docker79 manifests]# kubectl exec -it liveness-httpget-pod -- /bin/sh  / # ls /usr/share/nginx/html/  50x.html    index.html  / # rm /usr/share/nginx/html/index.html -f  / # exit  [root@docker79 manifests]# kubectl get pods -o wide  NAME                   READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  liveness-httpget-pod   1/1       Running   1          2m        10.244.1.13   docker78   <none>  pod-demo               1/1       Running   0          2h        10.244.2.9    docker77   <none>  [root@docker79 manifests]#

說明:當httpGetAction探針探測到無法訪問 /index.html 時,立即執行restartPolicy重啟策略,該策略默認值always,所以可以看到 pod 的 restarts 為1.

例3-readiness:

 [root@docker79 manifests]# vim readiness-httpget.yaml  [root@docker79 manifests]# cat readiness-httpget.yaml  apiVersion: v1  kind: Pod  metadata:    name: readiness-httpget-pod    namespace: default  spec:    containers:    - name: readiness-httpget-container      image: nginx:1-alpine      imagePullPolicy: IfNotPresent      ports:      - name: http        containerPort: 80      readinessProbe:        httpGet:          port: http          path: /index.html        initialDelaySeconds: 1        periodSeconds: 3  [root@docker79 manifests]# kubectl apply -f readiness-httpget.yaml  pod/readiness-httpget-pod created  [root@docker79 manifests]# kubectl get pods -o wide  NAME                    READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  pod-demo                1/1       Running   0          3h        10.244.2.9    docker77   <none>  readiness-httpget-pod   1/1       Running   0          9s        10.244.1.14   docker78   <none>  [root@docker79 manifests]# kubectl exec -it readiness-httpget-pod -- /bin/sh  / # rm -f /usr/share/nginx/html/index.html  / #  [root@docker79 manifests]# kubectl get pods -o wide  NAME                    READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  pod-demo                1/1       Running   0          3h        10.244.2.9    docker77   <none>  readiness-httpget-pod   0/1       Running   0          1m        10.244.1.14   docker78   <none>  [root@docker79 manifests]# kubectl exec -it readiness-httpget-pod -- /bin/sh  / # echo readiness > /usr/share/nginx/html/index.html  / # [root@docker79 manifests]#  [root@docker79 manifests]# kubectl get pods -o wide  NAME                    READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  pod-demo                1/1       Running   0          3h        10.244.2.9    docker77   <none>  readiness-httpget-pod   1/1       Running   0          2m        10.244.1.14   docker78   <none>  [root@docker79 manifests]#

說明:就緒探測與service 調度有緊密關聯,只有就緒的pod才能被調度。例3中當刪除/usr/share/nginx/html/index.html之後,探針無法獲取/index.html,所以pod的READY狀態處於0/1狀態;當再次創建/usr/share/nginx/html/index.html之後,探針有效探測到/index.html之後,pod的READY狀態處於1/1狀態。

例4-lifecycle:

[root@docker79 manifests]# vim lifecycle-poststart.yaml  [root@docker79 manifests]# cat lifecycle-poststart.yaml  apiVersion: v1  kind: Pod  metadata:    name: lifecycle-poststart-pod    namespace: default  spec:    containers:    - name: lifecycle-poststart-container      image: busybox:latest      imagePullPolicy: IfNotPresent      lifecycle:        postStart:          exec:            command: ["mkdir","-p","/var/www/inspiry"]      command: ["/bin/sh","-c","sleep 60; /bin/httpd -f -h /var/www/inspiry"]  [root@docker79 manifests]# kubectl apply -f lifecycle-poststart.yaml  pod/lifecycle-poststart-pod created  [root@docker79 manifests]# kubectl get pods -o wide  NAME                      READY     STATUS    RESTARTS   AGE       IP            NODE       NOMINATED NODE  lifecycle-poststart-pod   1/1       Running   0          9s        10.244.1.15   docker78   <none>  [root@docker79 manifests]# kubectl exec -it lifecycle-poststart-pod -- /bin/sh  / # ls /var/www/  inspiry  / # netstat -tnlp  Active Internet connections (only servers)  Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name  tcp        0      0 :::80                   :::*                    LISTEN      1/httpd  / # exit  [root@docker79 manifests]#

說明:例4中使用lifecycle.postStart.exec 表示pod中container啟動後執行的命令.