Docker+K8s基礎篇(三)
-
kubernetes上的資源
- A:k8s上的常用資源
-
Pod的配置清單
- A:Pod上的清單定義
- B:Pod創建資源的方法
- C:spec下其它字段的介紹
-
Pod的生命周期
- A:Pod的生命周期階段
- B:容器的兩種探測(探針)
- C:容器啟動后和終止前鈎子
♣一:kubernetes的資源
A:k8s上的常用資源:
1:workload(工作負載型對象):
pod,Replicaset,Deployment,statefulSet,DaemonSet,Job,Cronjob,.....(以及各種各樣的pod控制器)deployment
2:服務發現和負載均衡:
Service,Ingress,....
3:配置和存儲:
Volume,CSI(K8S上的容器存儲接口,用來擴展各種第三方的存儲卷)
配置相關:
ConfigMap(配置中心類型的存儲對象),Secret(主要功能和ConfigMap相似,但是用於存儲敏感數據),.....
外部信息輸出給容器:
DownwardAPI,......
4:集群級的資源:(之前的pod資源默認都是在default名稱空間里面的),但是有些資源需要在集群級內部進行定義。
Namespace,Node,Role(角色),ClusterRole(集群角色),RoleBinding(角色綁定),ClusteRoleBinding(集群角色綁定)
5:元數據型資源:
HPA,PodTemplate(用於控制器創建pod的模板),LimitRange(定義資源限制)
♣二:Pod的配置清單
A:Pod上的清單定義:
我們前面都使用命令來創建pods,但是這種形式創建pods資源的時候不能人為的定義其內部的配置。

[root@www .kube]# kubectl get pod myapp-5bc569c47d-jh6qk -o yaml (我們可以通過查看pods資源信息的時候加上-o yaml來查看pods資源的詳細信息,而這些詳細信息的展示方式也是我們接下來要使用的配置清單來創建pods資源的形式。 apiVersion: v1 api群組的名稱和版本 在實際定義中我們會使用group(組名)/version(版本)來定義的,如果沒有定義組名,默認是cron(核心組) kind: Pod 資源類別 metadata: 元數據 creationTimestamp: "2019-06-23T03:39:45Z" generateName: myapp-5bc569c47d- labels: pod-template-hash: 5bc569c47d run: myapp name: myapp-5bc569c47d-jh6qk namespace: default ownerReferences: - apiVersion: apps/v1 blockOwnerDeletion: true controller: true kind: ReplicaSet name: myapp-5bc569c47d uid: 8b17b969-9568-11e9-9101-000c291028e5 resourceVersion: "8087" selfLink: /api/v1/namespaces/default/pods/myapp-5bc569c47d-jh6qk uid: 8b1c0e97-9568-11e9-9101-000c291028e5 spec: 規格,定義我們要創建的資源需要滿足什么規范和特性(這個字段下的內容從定義之初就已經決定了pods資源啟動之后的特性) containers: - image: ikubernetes/myapp:v1 imagePullPolicy: IfNotPresent name: myapp resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: default-token-7bd8r readOnly: true dnsPolicy: ClusterFirst enableServiceLinks: true priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default terminationGracePeriodSeconds: 30 tolerations: 容忍度(污點) - effect: NoExecute key: node.kubernetes.io/not-ready operator: Exists tolerationSeconds: 300 - effect: NoExecute key: node.kubernetes.io/unreachable operator: Exists tolerationSeconds: 300 volumes: - name: default-token-7bd8r secret: defaultMode: 420 secretName: default-token-7bd8r status: 這個字段定義了pods資源在當前的狀態,上面的spec定義初始狀態,status則定義當前狀態(只讀),如果我們定義的spec狀態和后面運行的status當前狀態不統一,k8s會自動把當前狀態向目標狀態轉移或靠攏,直到滿足用戶期望的狀態。 conditions: - lastProbeTime: null lastTransitionTime: "2019-06-23T03:39:45Z" message: '0/3 nodes are available: 3 node(s) had taints that the pod didn''t tolerate.' reason: Unschedulable status: "False" type: PodScheduled phase: Pending qosClass: BestEffort [root@www .kube]#
B:Pod創建資源的方法:
不是所有的資源都能接受yaml格式定義的資源,例如apiservice就只能接受JSON格式的資源定義,但是JSON格式在定義起來不如yaml格式的方便,如果使用yaml格式來提供配置清單,apiservice能無損切自動的江yaml格式的清單轉換成JSON格式,然后提交直到運行。
配置清單的字段組成:
1:apiVersion(用來定義當前屬於哪個組和那個版本,這個直接關系到最終提供使用的是那個版本)
通過命令kubectl api-versions可以查看到當前所有api的版本。

[root@www .kube]# kubectl api-versions k8s將api的版本都以組的形式來划分,這樣我們后面如果是對版本升級,只需要對組內的版本升級即可,避免全部版本都受到影響。而且分組之后還能在一個組里面定義多個版本,來實現多版本並存。 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 autoscaling/v2beta2 在各組的版本之間還分為了穩定版本(v1),穩定版表示定義好的接口在后續不會再進行變化,萬一有變化也是在已有的接口上來增加新的接口。 非穩定版本(beta),表示定義的接口還會進行變化。 batch/v1 batch/v1beta1 certificates.k8s.io/v1beta1 coordination.k8s.io/v1 coordination.k8s.io/v1beta1 events.k8s.io/v1beta1 extensions/v1beta1 networking.k8s.io/v1 networking.k8s.io/v1beta1 node.k8s.io/v1beta1 policy/v1beta1 rbac.authorization.k8s.io/v1 rbac.authorization.k8s.io/v1beta1 scheduling.k8s.io/v1 scheduling.k8s.io/v1beta1 storage.k8s.io/v1 storage.k8s.io/v1beta1 v1 [root@www .kube]#
2:kind(資源類別)用來定義創建的對象是屬於什么類別,是pod,service,還是deployment等對象,可以按照其固定的語法格式來自定義。
3:metadata(元數據):
提供以下幾個字段:
creationTimestamp: "2019-06-24T12:18:48Z"
generateName: myweb-5b59c8b9d-
labels: (對象標簽)
pod-template-hash: 5b59c8b9d
run: myweb
name: myweb-5b59c8b9d-gwzz5 (pods對象的名稱,同一個類別當中的pod對象名稱是唯一的,不能重復)
namespace: default (對象所屬的名稱空間,同一名稱空間內可以重復,這個名稱空間也是k8s級別的名稱空間,不和容器的名稱空間混淆)
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: myweb-5b59c8b9d
uid: 37f38f64-967a-11e9-8b4b-000c291028e5
resourceVersion: "943"
selfLink: /api/v1/namespaces/default/pods/myweb-5b59c8b9d-gwzz5
uid: 37f653a6-967a-11e9-8b4b-000c291028e5
annotations(資源注解,這個需要提前定義,默認是沒有的)
通過這些標識定義了每個資源引用的path:即/api/group/version/namespaces/名稱空間/資源類別/對象名稱
4:spec (這個字段最重要,因為spec是用來定義目標狀態的‘disired state’,而且資源不通導致spec所嵌套的字段也各不相同,也就因為spec重要且字段不相同,k8s在內部自建了一個spec的說明用於查詢)
5:status:(當前狀態,’current state‘,這個字段有kubernetes集群來生成和維護,不能自定義,屬於一個只讀字段)
spec字段的定義說明:

[root@www kubeadm]# kubectl explain pods(通過explain參數加上資源類別就能看到該資源應該怎么定義) KIND: Pod VERSION: v1 DESCRIPTION: Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts. FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources kind <string> Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds metadata <Object> 在相應的字段下面只要看到Object就可以知道該字段下面是要嵌套很多二級字段的,但是二級字段我們還是不知道怎么去定義。 Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata spec <Object> Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status status <Object> Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status [root@www kubeadm]# kubectl explain pods.metadata 通過資源類別加上帶有Object標記的字段,我們就可以看到一級字段下二級字段的內容有那些怎么去定義等 KIND: Pod VERSION: v1 RESOURCE: metadata <Object> DESCRIPTION: Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. FIELDS: annotations <map[string]string> 二級字段加上map標記代表是映射字段,其字段是有k=v數據組成的json數組 Annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations clusterName <string> The name of the cluster which the object belongs to. This is used to distinguish resources with same name and namespace in different clusters. This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request. creationTimestamp <string> ......... ownerReferences <[]Object> 二級字段下面還可以嵌套三級字段,和上面方法一樣[root@www kubeadm]# kubectl explain pods.metadata.ownerReferences,通過加上不同級別的字段名稱來看下字段下的內容,而且前面的[]號代表對象列表 (如果字段后面加上了-required-就代表這個字段是必選字段) ........
自定義yaml文件:
我們在創建yaml文件的時候可以先把上面5個一級字段寫下來,然后慢慢填空來完成:
apiVersion: v1
kind: Pod
metadata:
name: pod-number 而且這個位置的名字好像不支持大寫字母
namespace: default
labels: #這個位置可以使用{key:value,key:value.....}kv之間逗號隔開
app: myweb 注意這個位置的名字和下面創建image的時候的名字一致
tier: Not outside
spec:
containers:
- name: myweb
image: ikubernetes/myapp:v1
- name: busybox #如果有多個容器,還可以多定義幾個
image: busybox:latest 因為busybox默認是啟動的sh命令,我們可以給shell命令傳遞些參數。
command: (["/bin/sh","-c","sleep 20"] 傳遞的參數可以使用[]來寫,也可以用下面的形式來定義)
- "/bin/sh"
- "-c"
- "echo $(date) >> /usr/share/nginx/html/index.html; sleep 5"

[root@www TestYaml]# kubectl create -f pod-test.yaml 然后使用create參數-f去指定加載的yaml文件名 pod/pod-number created [root@www TestYaml]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-kk 1/1 Running 0 88s pod-number 1/2 CrashLoopBackOff 4 5m59s可以看到pod-number已經被創建
我們定義了兩個容器,正在運行的有一個,我們可以通過命令來查看通過yaml創建的文件的詳細信息

[root@www TestYaml]# kubectl describe pods pod-number 通過describe參數來查看pods的詳細信息 Name: pod-number Namespace: default Priority: 0 PriorityClassName: <none> Node: www.kubernetes.node1.com/192.168.181.140 運行在哪個節點上 Start Time: Wed, 26 Jun 2019 21:05:36 +0800 Labels: app=myweb tier=Not-outside Annotations: <none> Status: Running 可以看到名稱叫myweb狀態是運行中 IP: 10.244.1.19 Containers: myweb: Container ID: docker://4b213ff75852bf943adc4a4f35dfb41dd881ac10b051bd545ca00f8bdbcb9ab1 Image: ikubernetes/myapp:v1 Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513 Port: <none> Host Port: <none> State: Running Started: Wed, 26 Jun 2019 21:05:41 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-n5fjx (ro) busybox: Container ID: docker://e2b6b439439202e1887b3182b3155bb7e6798460be48c42edafda046ef907e8f Image: busybox:latest Image ID: docker-pullable://busybox@sha256:7a4d4ed96e15d6a3fe8bfedb88e95b153b93e230a96906910d57fc4a13210160 Port: <none> Host Port: <none> Command: /bin/sh -c echo $(date) >> /usr/share/nginx/html/index.html; sleep 5 State: Waiting 因為我們第二個容器創建之后運行的命令是有問題的,所有狀態也是顯示不正常的 Reason: CrashLoopBackOff Last State: Terminated Reason: Completed Exit Code: 0 Started: Wed, 26 Jun 2019 21:27:15 +0800 Finished: Wed, 26 Jun 2019 21:27:20 +0800 Ready: False Restart Count: 8 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-n5fjx (ro) Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled True Volumes: default-token-n5fjx: Type: Secret (a volume populated by a Secret) SecretName: default-token-n5fjx Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: 在這個字段信息下,我們可以看到整個yaml格式創建pods的過程 Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 26m default-scheduler Successfully assigned default/pod-number to www.kubernetes.node1.com Normal Created 25m kubelet, www.kubernetes.node1.com Created container myweb Normal Pulled 25m kubelet, www.kubernetes.node1.com Container image "ikubernetes/myapp:v1" already present on machine Normal Started 25m kubelet, www.kubernetes.node1.com Started container myweb Warning Failed 25m kubelet, www.kubernetes.node1.com Failed to pull image "busybox:latest": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/library/busybox/manifests/latest: Get https://auth.docker.io/token?scope=repository%3Alibrary%2Fbusybox%3Apull&service=registry.docker.io: net/http: TLS handshake timeout Warning Failed 25m (x2 over 25m) kubelet, www.kubernetes.node1.com Error: ErrImagePull Warning Failed 25m kubelet, www.kubernetes.node1.com Failed to pull image "busybox:latest": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout Warning Failed 24m (x2 over 25m) kubelet, www.kubernetes.node1.com Error: ImagePullBackOff Normal BackOff 24m (x2 over 25m) kubelet, www.kubernetes.node1.com Back-off pulling image "busybox:latest" Normal Started 24m (x2 over 24m) kubelet, www.kubernetes.node1.com Started container busybox Normal Pulling 23m (x5 over 25m) kubelet, www.kubernetes.node1.com Pulling image "busybox:latest" Normal Created 23m (x3 over 24m) kubelet, www.kubernetes.node1.com Created container busybox Normal Pulled 15m (x7 over 24m) kubelet, www.kubernetes.node1.com Successfully pulled image "busybox:latest" Warning BackOff 54s (x89 over 23m) kubelet, www.kubernetes.node1.com Back-off restarting failed container
查看pods日志:
因為我們創建busybox的是狀態是有問題的,我們就可以通過命令來查看。

[root@www TestYaml]# kubectl logs pod-number busybox 我們通過logs參數指定查看pods里面容器的日志 /bin/sh: can't create /usr/share/nginx/html/index.html: nonexistent directory 可以看到報錯內容,方便我們去查詢容器的錯誤 [root@www TestYaml]# curl 10.244.1.19 因為我們創建的myweb是正常運行,但是沒有訪問請求,我們自己訪問下myweb制造訪問請求 Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a> [root@www TestYaml]# kubectl logs pod-number myweb 10.244.0.0 - - [26/Jun/2019:13:41:35 +0000] "GET / HTTP/1.1" 200 65 "-" "curl/7.29.0" "-" 可以看到來自master在什么時間對myweb進行了訪問
創建好的容器我們也可以和docker一樣通過命令到容器里面去操作。

[root@www TestYaml]# kubectl exec --help 可以使用exec命令來操作 命令行格式 Usage: kubectl exec POD [-c CONTAINER] -- COMMAND [args...] [options] 注意command前面的--是固定格式 [root@www TestYaml]# kubectl exec -it pod-number -c myweb -- /bin/sh / # [root@www TestYaml]# kubectl get pods NAME READY STATUS RESTARTS AGE pod-kk 1/1 Running 0 45m pod-number 1/2 ErrImagePull 12 49m
基於yaml文件刪除pods。

[root@www TestYaml]# kubectl delete -f pod-test.yaml 我們在刪除pods資源的時候可以基於yaml文件定義的pods資源來刪除,這樣我們即使刪除了pods,但是yaml文件還存在,想創建隨時可以create下就能出來,無需每次都run,避免人為命令行run的時候導致的問題 pod "pod-kk" deleted [root@www TestYaml]# kubectl get pods 而且在基於yaml文件刪除的時候發現刪除的pods不在會被自動創建了,也就是說pods不在受控制器管理了,想刪除隨時可以刪除和創建 NAME READY STATUS RESTARTS AGE pod-number 1/2 Running 13 50m
我們上面只是寫了一個最簡單yaml,其實yaml能更好的按照我們的期許或者更加可控的形式來創建pods,yaml形式大大的彌補了pods自定義這個概念,使得最大限度上pods是按照約束和規范來創建的。
kubectl管理資源有三種方式:
1:命令管理法;
2:配置清單管理法(聲明式);
配置清單式好處是不言而喻的,可以隨時修改和創建,極大的規避了錯誤的產生。
3:通過其它命令的配置清單管理法。
我們上面創建的pods是沒有持久存儲功能的,要想完成持久存儲,必須脫離k8s集群節點之外的網絡存儲節點,這種存儲節點都是具有持久存儲的節點。
C:spec下其它字段的介紹:
我們可以通過explain一層層的從一級字段(例如spec)往下看。

[root@www TestYaml]# kubectl explain pods.spec.containers.imagePullPolicy KIND: Pod VERSION: v1 FIELD: imagePullPolicy <string> DESCRIPTION: Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images imagePullPolicy字段定義了三種鏡像獲取的方式,而且當對象一旦被創建之后,改字段是不被允許的。 Always:總是去倉庫里面拖鏡像,而且如果鏡像標簽是latest,就默認從倉庫獲取鏡像; Never:總是以使用本地鏡像,本地沒有也不會去倉庫里面拖鏡像; IfNotPresent:當本地沒有才去倉庫拖鏡像,除了latest之外,其它的都遵循IfNotPresent模式。

[root@www TestYaml]# kubectl explain pods.spec.containers.ports 如果是創建的對象后面需要暴露端號出去,可以一次暴露多個端口,而且每個暴露出去的端口還可以自定義名字,最后還指明暴露的端口是什么協議 當然我們還注意的是例如對象是nginx,默認是80端口,及時在此不指定暴露的端口,默認也是暴露服務默認的端口。 KIND: Pod VERSION: v1 RESOURCE: ports <[]Object> DESCRIPTION: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. ContainerPort represents a network port in a single container. 那從實際的角度來說指定容器端口即可containerPort FIELDS: containerPort <integer> -required- Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536. hostIP <string> What host IP to bind the external port to. hostPort <integer> Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this. name <string> If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services. protocol <string> Protocol for port. Must be UDP, TCP, or SCTP. Defaults to "TCP". 沒有指定協議,默認是tcp的協議 案例: spec: containers: - name: myweb1 image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80 可以一次暴露多個端口 - name: https containerPort: 443

[root@www TestYaml]# kubectl explain pods.spec.containers.args args指默認向command(命令)傳遞參數 KIND: Pod VERSION: v1 FIELD: args <[]string> DESCRIPTION: Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell [root@www TestYaml]# kubectl explain pods.spec.containers.command command指向要運行的對象給與默認執行的命令或者程序 KIND: Pod VERSION: v1 FIELD: command <[]string> DESCRIPTION: Entrypoint array. Not executed within a shell(默認給出的命令是不會運行在shell里面的,如果想運行在sehll里面需要自己指定 ). The docker image's ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
在args和command和dockerfile里面的entypoint和cmd是存在一定關系的:
當沒有提供args和command的時候就運行鏡像里面的entypoint和cmd;
如果只提供了command,沒有提供args,那鏡像里面的entypoint和cmd都被忽略;
當只定義了args,默認會將args當參數傳遞給entypoint,這個時候鏡像里面的cmd將不再生效;
當提供了args和command兩種,鏡像里面的entypoint和cmd就將失效了。
標簽:
標簽是k8s上一個重要的對象聲明,標簽具有以下特征:
一個對象可以有多個標簽,一個標簽也可以貼在多個對象上;
標簽即可以在被創建的時候定義,也可以在創建之后來增加,修改和刪除;
以便於對象被創建之后,方便調度器做匹配度檢查,從而達到目標對象。
標簽在定義的時候應該考慮到以下幾個部分:
1:對象的版本(穩定版,開發版,公測版,內存版)
2:環境標簽(測試版,開發版本)
3:對象提供的功能(web服務,代理服務,數據庫服務等等)
4:分區標簽(用戶a,用戶b等等)
5:品控標簽(月級定時追蹤,周級定時追蹤等等)
標簽的定義需要遵循:
key:字母,數字,_,-,. 字符,且不能超過63個字符;
value;其它和key相同,但是可以為空。

[root@www TestYaml]# kubectl get pods --show-labels 通過參數--show-labels來查看對象標簽 NAME READY STATUS RESTARTS AGE LABELS pod-yy 1/1 Running 0 61m app=myweb1,tier=Not-outside [root@www TestYaml]# kubectl get pods -L app 加-L參數值過濾查詢對象標簽的值 NAME READY STATUS RESTARTS AGE APP pod-kk 1/1 Running 1 2m57s mypod01 pod-yy 1/1 Running 0 66m myweb1 [root@www TestYaml]# kubectl get pods -l app --show-labels -l過濾查看指包含app這個標簽一類的對象 NAME READY STATUS RESTARTS AGE LABELS pod-kk 1/1 Running 1 5m6s app=mypod01,tier=Not-outside pod-yy 1/1 Running 0 68m app=myweb1,tier=Not-outside

Usage: kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version] [options] [root@www TestYaml]# kubectl label pods pod-kk edition=beta_version pod/pod-kk labeled [root@www TestYaml]# kubectl get pods pod-kk --show-labels 可以看到新的標簽已經標記完成 NAME READY STATUS RESTARTS AGE LABELS pod-kk 1/1 Running 1 11m app=mypod01,edition=beta_version,tier=Not-outside

k8s的標簽選擇器支持兩種方式來進行選擇性查詢: 等值關系的標簽選擇器: 支持:=,==,!= [root@www TestYaml]# kubectl get pods -l app=mypod01 --show-labels 等於 NAME READY STATUS RESTARTS AGE LABELS pod-kk 1/1 Running 1 20m app=mypod01,edition=beta_version,tier=Not-outside [root@www TestYaml]# kubectl get pods -l app!=mypod01 --show-labels 不等於 NAME READY STATUS RESTARTS AGE LABELS pod-yy 1/1 Running 0 83m app=myweb1,tier=Not-outside [root@www TestYaml]# kubectl get pods -l app=mypod01,edition=beta_version --show-labels 同時滿足多個條件的 NAME READY STATUS RESTARTS AGE LABELS pod-kk 1/1 Running 1 22m app=mypod01,edition=beta_version,tier=Not-outside 集合關系的標簽選擇器: key in (value1,value2) key notin (value1,value2) key和!key [root@www TestYaml]# kubectl get pods -l "edition in (beta_version)" --show-labels NAME READY STATUS RESTARTS AGE LABELS pod-kk 1/1 Running 1 37m app=mypod01,edition=beta_version,tier=Not-outside [root@www TestYaml]#
在k8s上我們很多資源都需要通過標簽和標簽選擇器來關聯其它的資源,例如pod控制器和service,針對這種資源我們通常會使用兩個字段來嵌套關聯其它資源
1:matchLabesl;直接給定鍵值
2:matchExpressions;基於給定的表達式來定義使用的選擇器
{key:“KEY",operator:"OPERATOR",values:[value1,value2....]}
表示定義的key的values值基於operator來做比較,能滿足即表示滿足我們的需求,否則就不能滿足我們的需求
operator表示操操作符,常用的有:In,Notin,Exists(存在),NotExists(不存在)
使用In,Notin后面的values必須是一個非空列表
Exists,NotExists的valuel必須是一個空列表
k8s上很多資源都可以打標簽,例如nodes等。

[root@www TestYaml]# kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS beta.kubernetes.io是前綴,這個前綴是dns域名 www.kubernetes.master.com Ready master 142m v1.14.1 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=www.kubernetes.master.com,kubernetes.io/os=linux,node-role.kubernetes.io/master= www.kubernetes.node1.com Ready <none> 140m v1.14.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=www.kubernetes.node1.com,kubernetes.io/os=linux www.kubernetes.node2.com Ready <none> 140m v1.14.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=www.kubernetes.node2.com,kubernetes.io/os=linux [root@www TestYaml]#

nodeSelector節點選擇器,可以選擇pod在哪個節點上運行,這樣我們可以指定該pod在哪個或者哪類節點上運行,因為我們幾點資源不都是一樣的,有的可能是虛擬機和雲機,有的是ibm或者dell的實體機等,針對這種我們做監控也得有針對性的運行pods [root@www TestYaml]# kubectl explain pods.spec.nodeSelector KIND: Pod VERSION: v1 FIELD: nodeSelector <map[string]string> 注意字段的類型 DESCRIPTION: NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ spec: containers: - name: mypod01 image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80 - name: https containerPort: 443 nodeSelector: 例如我們定義改pods只能運行在帶有IBM標簽的機器上,當然得事先定義帶IMB的標簽 lable: IBM 如果不想這么麻煩,我就想直接指定節點,也可以,字段是nodeName [root@www TestYaml]# kubectl explain pods.spec.nodeName KIND: Pod VERSION: v1 FIELD: nodeName <string> DESCRIPTION: NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.

annotations:資源注解,這個label不同的是,不能作為標簽選擇器的挑選機制所存在,只能為對象提供元數據,而且資源描述是沒有字符限制的。當創建的大型且重要對象的適合,資源描述尤為重要。 [root@www TestYaml]# cat pod-test.yaml apiVersion: v1 kind: Pod metadata: name: pod-kk namespace: default labels: app: mypod01 tier: Not-outside annotations: 我們定義了三個資源的描述 creator: "Tommy" create_time: "2019-06-30" Contact_information: "baidu@163.com" spec: containers: - name: mypod01 image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80 - name: https containerPort: 443 nodeSelector: lable: IBM [root@www TestYaml]# kubectl create -f pod-test.yaml pod/pod-kk created [root@www TestYaml]# kubectl describe pods pod-kk Name: pod-kk Namespace: default Priority: 0 PriorityClassName: <none> Node: <none> Labels: app=mypod01 tier=Not-outside Annotations: Contact_information: baidu@163.com 可以看到Annotations的信息,但是不是安裝我們定義的順序來的,但是無關緊要。 create_time: 2019-06-30 creator: Tommy Status: Pending IP: Containers: mypod01: Image: ikubernetes/myapp:v2 Ports: 80/TCP, 443/TCP Host Ports: 0/TCP, 0/TCP Environment: <none> ..........
♣三:Pod的生命周期
A:Pod的生命周期階段:
一個pods的生命周期需要經歷一下幾個階段:
1:pod被創建到運行為一個階段;
2:pods在被創建之后到運行為容器之前有一段的空閑時間,這個時間有可能需要給容器做一些環境的初始化。
3:當pods被運維為容器的最開始,容器本身需要最環境的初始化,例如容器如果是nginx,nginx需要對html路徑下的文件按照順序加載等等,當然容器有開始就有結束,結束的時候對容器產生的數 據進行處理;
4:容器在運行的過程中我們需要對容器做監控,存活性狀態檢測。
pod的生命周期按照狀態來划分可以分為一下幾個部分:
1:Pending(掛起),pods為什么會掛起,pods運行的時候是按照yaml文件來運行的,當節點環境不能滿足pods運行就會處於掛起,也代表調度尚未完成;
2:Running(運行)
3:Failed(失敗)
4:Succeeded(成功)
5:Unknown(未知狀態)
等等狀態
pods創建的過程:
當用戶創建pods的時候,這個請求會傳遞給apiservice,apisevice接收到請求之后會保存在etcd當中,接下來apiservice會請求scheduler來進行調度,如果調度成功了會將調度的結果保存在etcd的poids資源狀態信息當中,
被調度的節點上的kubelet會得到這個保存的狀態知道有一個新任務給到自己了,kubelet拿到清單之后並啟動運行這個pods,pods創建的狀態對由kubelet發送給apiservice保存在etcd當中。
pod生命周期中的重要行為,初始化容器,容器探測。
pod的重啟:

[root@www TestYaml]# kubectl explain pods.spec.restartPolicy restartPolicy用來給重啟容器,當探測到容器掛了,restartPolicy會提供三種選項給用戶,Always(總是重啟),OnFailure(只有正常終止的才重啟),Never(從不重啟) KIND: Pod VERSION: v1 FIELD: restartPolicy <string> DESCRIPTION: Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
pods的重啟不是我們常規理解的一旦服務退出就立馬重啟,周而復始的重啟,因為每一次重啟都會消耗我們的硬件資源的,如果不能合理處理這種情況,可能我們機器硬件資源就用完了,影響到其他的程序,所以pods的重啟是第一次掛了立馬重啟,
當第二次掛了是延時重啟,每一次重啟就要在上一次時間上翻倍,直到最大時長300秒,到300秒一會代表pods每一次重啟都需要300秒。當pods節點沒有掛或者pods沒有被刪除,就一直會在此節點上重啟。
pod的終止:
pod的終止需要遵循平滑終止的策略,主要是為了保證我們的數據不會丟失,當用戶或者外在因素終止了pods,pods首先會想其內部的容器發起終止信號,讓pods中的容器自然終止,這個終止是有時間限制的,例如10秒,10秒沒有終止,就會發起kill信號。
這個寬限的時間默認是30秒,也可以自行定義。
B:容器的兩種探測(探針)
liveness probe(存活性探測)和readiness probe(就緒性探測)
容器的探測和我們生活常見的探測一樣,在容器里面安裝一些傳感器或者探針等,來獲取一些數據來作為容器是否存活或者就緒的標准,目前k8s上對兩種狀態的探測方式是一樣的。
三種探測(探針)類型:
1:ExecAction
2:TCPSocketAction(tcp套接字探測)
3:HTTPGetAction(如果對象是http服務,我們直接發送http的請求即可達到探測目的)
上述三種針對兩種不同的狀態又分為了存活性探針或者就緒性探針,還有這個探測是用來探測容器的,不是pods。

[root@www home]# kubectl explain pod.spec.containers.livenessProbe KIND: Pod VERSION: v1 RESOURCE: livenessProbe <Object> DESCRIPTION: Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic. FIELDS: exec <Object> 第一種 One and only one of the following should be specified. Exec specifies the action to take. failureThreshold <integer> 指定探測的多少次都是失敗的,才認為是失敗的 Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3(默認是3此). Minimum value is 1.(最少是一次) httpGet <Object> 第二種 HTTPGet specifies the http request to perform. initialDelaySeconds <integer> 在docker容器在啟動的時候立即做探測,這個時候可能主程序還沒有啟動完成,這個時候探測結果有可能是失敗造成誤傷,在多長時間之后進行探測 Number of seconds after the container has started before liveness probes 默認是容器一旦啟動就立馬探測 are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes periodSeconds <integer> 指定探測次數之后間隔多長時間來進行探測 How often (in seconds) to perform the probe. Default to 10 (默認是10秒探測一次)seconds. Minimum value is 1. successThreshold <integer> Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1. tcpSocket <Object>第三種 TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported timeoutSeconds <integer> 指定探測間隔時間之后超時多長時間 Number of seconds after which the probe times out. Defaults to 1(默認是1秒) second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes 上面三種探針,我們一次創建指需要定義一個足以

[root@www home]# kubectl explain pod.spec.containers.readinessProbe KIND: Pod VERSION: v1 RESOURCE: readinessProbe <Object> 探測方式和livenessProbe一樣的,但是需要分清楚兩者之間的屬性,程序存活不代表程序就是就緒的 DESCRIPTION: Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes Probe describes a health check to be performed against a container to determine whether it is alive or ready to receive traffic. FIELDS: exec <Object> One and only one of the following should be specified. Exec specifies the action to take. failureThreshold <integer> Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. httpGet <Object> HTTPGet specifies the http request to perform. initialDelaySeconds <integer> Number of seconds after the container has started before liveness probes are initiated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes periodSeconds <integer> How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. successThreshold <integer> Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1. tcpSocket <Object> TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported timeoutSeconds <integer> Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes
除了上述兩種,k8s還提供了生命周期的探測。

[root@www home]# kubectl explain pod.spec.containers.lifecycle 這個什么周期是用來定義容器啟動前和終止后的鈎子參數的 KIND: Pod VERSION: v1 RESOURCE: lifecycle <Object> DESCRIPTION: Actions that the management system should take in response to container lifecycle events. Cannot be updated. Lifecycle describes actions that the management system should take in response to container lifecycle events. For the PostStart and PreStop lifecycle handlers, management of the container blocks until the action is complete, unless the container process fails, in which case the handler is aborted. FIELDS: postStart <Object> PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks preStop <Object> PreStop is called immediately before a container is terminated due to an API request or management event such as liveness probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod's termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod's termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks exec說明:

[root@www TestYaml]# kubectl explain pod.spec.containers.livenessProbe.exec KIND: Pod VERSION: v1 RESOURCE: exec <Object> DESCRIPTION: One and only one of the following should be specified. Exec specifies the action to take. ExecAction describes a "run in container" action. FIELDS:要想使用exec命令必須是容器里面程序擁有並且能執行的命令才可以 command <[]string> Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions ('|', etc) won't work. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.

[root@www TestYaml]# cat pod-test.yaml apiVersion: v1 kind: Pod metadata: name: busybox-test namespace: default spec: containers: - name: busybox-test-pod image: busybox:latest command: ["bin/sh","-c","touch /home/busybox; sleep 20; mv /home/busybox /tmp/; sleep 1200"] 我們給定命令讓對象啟動為容器之后執行的命令 livenessProbe: exec: 使用exec加上命令對這個容器運行之后創建的文件進行命令的探測 command: ["test","-e","/home/busybox"] initialDelaySeconds: 3 在容器啟動后3秒才開始探測 periodSeconds: 4 每隔4秒探測一次 [root@www TestYaml]# kubectl create -f pod-test.yaml pod/busybox-test created [root@www TestYaml]# kubectl get pods -w NAME READY STATUS RESTARTS AGE busybox-test 1/1 Running 0 46s 可以看到pods開始是running的 pod-kk 0/1 Pending 0 19m [root@www TestYaml]# kubectl describe pods busybox-test Name: busybox-test Namespace: default Priority: 0 PriorityClassName: <none> Node: www.kubernetes.node1.com/192.168.181.140 Start Time: Mon, 01 Jul 2019 21:01:03 +0800 Labels: <none> Annotations: <none> Status: Running 容器狀態是running和實際的狀態相符 IP: 10.244.1.22 Containers: busybox-test-pod: Container ID: docker://dce312cf24767a597ee177cf65d83686d1cf0a12a638708eb2810e78a18ab0de Image: busybox:latest Image ID: docker-pullable://busybox@sha256:7a4d4ed96e15d6a3fe8bfedb88e95b153b93e230a96906910d57fc4a13210160 Port: <none> Host Port: <none> Command: bin/sh -c touch /home/busybox; sleep 20; mv /home/busybox /tmp/; sleep 1200 State: Waiting Reason: CrashLoopBackOff Last State: Terminated 但是看到最近一次的狀態是結束的 Reason: Error 原因是錯誤 Exit Code: 137 退出的代碼是137 Started: Mon, 01 Jul 2019 21:19:55 +0800 啟動的時間 Finished: Mon, 01 Jul 2019 21:20:57 +0800 完成的時間 Ready: False Restart Count: 9 已經幫忙重啟了9次 Liveness: exec [test -e /home/busybox] delay=3s timeout=1s period=4s #success=1 #failure=3 可以看到詳細的探測過程 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-npzp7 (ro) Conditions: Type Status Initialized True Ready False ContainersReady False PodScheduled True Volumes: default-token-npzp7: Type: Secret (a volume populated by a Secret) SecretName: default-token-npzp7 Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 20m default-scheduler Successfully assigned default/busybox-test to www.kubernetes.node1.com Normal Pulled 17m (x3 over 20m) kubelet, www.kubernetes.node1.com Successfully pulled image "busybox:latest" Normal Created 17m (x3 over 20m) kubelet, www.kubernetes.node1.com Created container busybox-test-pod Normal Started 17m (x3 over 20m) kubelet, www.kubernetes.node1.com Started container busybox-test-pod Warning Unhealthy 17m (x9 over 19m) kubelet, www.kubernetes.node1.com Liveness probe failed: Normal Killing 17m (x3 over 19m) kubelet, www.kubernetes.node1.com Container busybox-test-pod failed liveness probe, will be restarted Normal Pulling 9m57s (x8 over 20m) kubelet, www.kubernetes.node1.com Pulling image "busybox:latest" Warning BackOff 21s (x36 over 12m) kubelet, www.kubernetes.node1.com Back-off restarting failed container [root@www TestYaml]# kubectl get pods -w NAME READY STATUS RESTARTS AGE busybox-test 0/1 ErrImagePull 9 26m pod-kk 0/1 Pending 0 44m busybox-test 1/1 Running 10 26m 可以看到RESTARTS的數字在變化,說明一直在幫忙重啟,標記的重啟次數。 [root@www TestYaml]# kubectl get pods -w NAME READY STATUS RESTARTS AGE busybox-test 0/1 ErrImagePull 9 26m pod-kk 0/1 Pending 0 44m busybox-test 1/1 Running 10 26m busybox-test 0/1 ErrImagePull 10 27m busybox-test 0/1 CrashLoopBackOff 10 27m 重啟10次之后直接顯示容器掛了

[root@www TestYaml]# kubectl explain pod.spec.containers.livenessProbe.tcpSocket KIND: Pod VERSION: v1 RESOURCE: tcpSocket <Object> DESCRIPTION: TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported TCPSocketAction describes an action based on opening a socket FIELDS: host <string> 必須要指定主機地址 Optional: Host name to connect to, defaults to the pod IP. port <string> -required- 必須指定從服務的那個端口來進行探測 Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.

httpGet探測 [root@www TestYaml]# kubectl explain pod.spec.containers.livenessProbe.httpGet 如果對象是一個http服務,你們可以直接使用httpGet來探測 KIND: Pod VERSION: v1 RESOURCE: httpGet <Object> DESCRIPTION: HTTPGet specifies the http request to perform. HTTPGetAction describes an action based on HTTP Get requests. FIELDS: host <string> Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead. httpHeaders <[]Object> Custom headers to set in the request. HTTP allows repeated headers. path <string> 直接像執行地址和端口的url發起請求,如果返回碼是200,301,302都是代表正常,其它代表錯誤 Path to access on the HTTP server. port <string> -required- Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.如果定義暴露的端口有指定名稱,可以通過命令來訪問也行 scheme <string> Scheme to use for connecting to the host. Defaults to HTTP.

[root@www TestYaml]# cat http-test-pod.yaml apiVersion: v1 kind: Pod metadata: name: http-test namespace: default spec: containers: - name: http-test-pod image: ikubernetes/myapp:v1 ports: - name: myhttp containerPort: 80 livenessProbe: httpGet: port: myhttp path: /index.html initialDelaySeconds: 3 periodSeconds: 4 [root@www TestYaml]# kubectl get pods NAME READY STATUS RESTARTS AGE busybox-test 0/1 CrashLoopBackOff 13 43m http-test 1/1 Running 0 12s pod-kk 0/1 Pending 0 61m [root@www TestYaml]# kubectl describe pods http-test Name: http-test Namespace: default Priority: 0 PriorityClassName: <none> Node: www.kubernetes.node2.com/192.168.181.146 Start Time: Mon, 01 Jul 2019 21:44:04 +0800 Labels: <none> Annotations: <none> Status: Running IP: 10.244.2.6 Containers: http-test-pod: Container ID: docker://67693dafae6c8b5f84bd344df045dbab0d5600fac67f42bfe00d06f1bfbc8b63 Image: ikubernetes/myapp:v1 Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513 Port: 80/TCP Host Port: 0/TCP State: Running Started: Mon, 01 Jul 2019 21:44:09 +0800 Ready: True Restart Count: 0 Liveness: http-get http://:myhttp/index.html delay=3s timeout=1s period=4s #success=1 #failure=3 可以看到整個探測的方式和詳細的參數和參數值 是通過httpget的形式不斷去的訪問index.html這個url Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-npzp7 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-npzp7: Type: Secret (a volume populated by a Secret) SecretName: default-token-npzp7 Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 81s default-scheduler Successfully assigned default/http-test to www.kubernetes.node2.com Normal Pulled 77s kubelet, www.kubernetes.node2.com Container image "ikubernetes/myapp:v1" already present on machine Normal Created 77s kubelet, www.kubernetes.node2.com Created container http-test-pod Normal Started 76s kubelet, www.kubernetes.node2.com Started container http-test-pod 我們手動進入容器把index.html文件改名字然后在查看 [root@www TestYaml]# kubectl exec -it http-test -- /bin/sh / # cd /usr/share/nginx/html/ /usr/share/nginx/html # ls 50x.html index.html /usr/share/nginx/html # mv index.html index.html.bak /usr/share/nginx/html # ls 50x.html index.html.bak /usr/share/nginx/html # [root@www TestYaml]# kubectl describe pods http-test Name: http-test Namespace: default Priority: 0 PriorityClassName: <none> Node: www.kubernetes.node2.com/192.168.181.146 Start Time: Mon, 01 Jul 2019 21:44:04 +0800 Labels: <none> Annotations: <none> Status: Running IP: 10.244.2.6 Containers: http-test-pod: Container ID: docker://850776a64342adae194fa117c6d53ca8baf1a672b33346169de8d687a16fd729 Image: ikubernetes/myapp:v1 Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513 Port: 80/TCP Host Port: 0/TCP State: Running Started: Mon, 01 Jul 2019 21:49:41 +0800 Last State: Terminated Reason: Completed Exit Code: 0 Started: Mon, 01 Jul 2019 21:44:09 +0800 Finished: Mon, 01 Jul 2019 21:49:40 +0800 Ready: True Restart Count: 1 可以看到已經在幫忙重啟了一次 Liveness: http-get http://:myhttp/index.html delay=3s timeout=1s period=4s #success=1 #failure=3 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-npzp7 (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-npzp7: Type: Secret (a volume populated by a Secret) SecretName: default-token-npzp7 Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 6m3s default-scheduler Successfully assigned default/http-test to www.kubernetes.node2.com Warning Unhealthy 27s (x3 over 35s) kubelet, www.kubernetes.node2.com Liveness probe failed: HTTP probe failed with statuscode: 404 Normal Killing 27s kubelet, www.kubernetes.node2.com Container http-test-pod failed liveness probe, will be restarted Normal Pulled 26s (x2 over 5m59s) kubelet, www.kubernetes.node2.com Container image "ikubernetes/myapp:v1" already present on machine Normal Created 26s (x2 over 5m59s) kubelet, www.kubernetes.node2.com Created container http-test-pod Normal Started 26s (x2 over 5m58s) kubelet, www.kubernetes.node2.com Started container http-test-pod [root@www TestYaml]# kubectl exec -it http-test -- /bin/sh / # cd /usr/share/nginx/html/ /usr/share/nginx/html # ls 50x.html index.html /usr/share/nginx/html # 因為我們創建的容器在重啟整個環境會被重置,重置之后index.html文件又因為環境的重置恢復了 [root@www TestYaml]# kubectl exec -it http-test -- /bin/sh ........ Last State: Terminated Reason: Completed Exit Code: 0 Started: Mon, 01 Jul 2019 21:44:09 +0800 Finished: Mon, 01 Jul 2019 21:49:40 +0800 Ready: True Restart Count: 1 Liveness: http-get http://:myhttp/index.html delay=3s timeout=1s period=4s #success=1 #failure=3 Environment: <none> [root@www TestYaml]# kubectl get pods NAME READY STATUS RESTARTS AGE busybox-test 0/1 CrashLoopBackOff 15 53m http-test 1/1 Running 1 10m 可以看到重啟的次數為1次 pod-kk 0/1 Pending 0 71m [root@www TestYaml]# kubectl logs http-test http-test-pod 10.244.2.1 - - [01/Jul/2019:13:49:44 +0000] "GET /index.html HTTP/1.1" 200 65 "-" "kube-probe/1.14" "-" 10.244.2.1 - - [01/Jul/2019:13:49:48 +0000] "GET /index.html HTTP/1.1" 200 65 "-" "kube-probe/1.14" "-" 10.244.2.1 - - [01/Jul/2019:13:49:52 +0000] "GET /index.html HTTP/1.1" 200 65 "-" "kube-probe/1.14" "-" ...... [root@www TestYaml]# kubectl logs http-test http-test-pod | wc -l 110 已經探測了110次了 [root@www TestYaml]# kubectl logs http-test http-test-pod 我們再刪除一次index.html,可以看到日志也提示了index.html文件不存在 2019/07/01 13:58:24 [error] 6#6: *131 open() "/usr/share/nginx/html/index.html" failed (2: No such file or directory), client: 10.244.2.1, server: localhost, request: "GET /index.html HTTP/1.1", host: "10.244.2.6:80" 10.244.2.1 - - [01/Jul/2019:13:58:24 +0000] "GET /index.html HTTP/1.1" 404 169 "-" "kube-probe/1.14" "-" ..... 重啟之后又立馬恢復正常
就緒性探測邏輯和存活性探測類似,其實我們在get pods的時候也能看到容器的大致情況
[root@www TestYaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
busybox-test 0/1 CrashLoopBackOff 17 61m
http-test 1/1 Running 2 18m
pod-kk 0/1 Pending 0 80m
在READY下面展示的0/1,其中前面的代表幾個容器已經就緒的,后面代表這個pods里面有幾個容器。但是這個前面的1是容器一啟動就代表就緒,但是實際上大多數情況下不代表實際的情況,所以需要去調整這個探測的時間。
如上圖所示,當service在調度的時候只要滿足名稱為web-pod條件的pod就會被自由調度,這個時候正好起了一個web-pod-003的pods,里面跑的容器和001和002一樣,如果我們設置的yaml文件是容器啟動就代表就緒,那此時有新用戶的請求進來被service
調度到003上,但是因為003上的容器內部的nginx和java都需要做啟動前環境檢測,nginx加載java文件等操作,這個操作也是會消耗時間,假如消耗時長為5秒,那這5秒之內將會有很多用戶的請求將得不到內容,此種也算作生產事故。由此可見我們設定
探測時間也變得尤為重要。

[root@www TestYaml]# cat readiness.http-get.yaml apiVersion: v1 kind: Pod metadata: name: readiness-http-test namespace: default spec: containers: - name: readiness-http-test-pod image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 readinessProbe: httpGet: port: http path: /index.html initialDelaySeconds: 3 periodSeconds: 4[root@www TestYaml]# kubectl get pods NAME READY STATUS RESTARTS AGE readiness-http-test 1/1 Running 0 12s [root@www TestYaml]# kubectl exec -it readiness-http-test -- /bin/sh / # cd /usr/share/nginx/html/ /usr/share/nginx/html # rm -rf index.html 刪掉主頁文件 /usr/share/nginx/html # ls 50x.html /usr/share/nginx/html # [root@www ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE readiness-http-test 1/1 Running 0 119s readiness-http-test 0/1 Running 0 2m38s 可以看到顯示未就緒狀態了 /usr/share/nginx/html # netstat -anptu | grep 80 而此時我們的nginx還是運行的狀態 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1/nginx: master pro tcp 0 0 10.244.1.23:80 10.244.1.1:37590 TIME_WAIT - tcp 0 0 10.244.1.23:80 10.244.1.1:37586 TIME_WAIT - /usr/share/nginx/html # touch index.html 我們手動touch一個index文件 /usr/share/nginx/html # ls 50x.html index.html /usr/share/nginx/html # [root@www ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE readiness-http-test 1/1 Running 0 119s readiness-http-test 0/1 Running 0 2m38s readiness-http-test 1/1 Running 0 6m2s 可以看到又變成就緒的狀態了
C:容器啟動后和終止前鈎子
postStart啟動后鈎子
preStop終止前鈎子

[root@www TestYaml]# kubectl explain pods.spec.containers.lifecycle KIND: Pod VERSION: v1 RESOURCE: lifecycle <Object> DESCRIPTION: Actions that the management system should take in response to container lifecycle events. Cannot be updated. Lifecycle describes actions that the management system should take in response to container lifecycle events. For the PostStart and PreStop lifecycle handlers, management of the container blocks until the action is complete, unless the container process fails, in which case the handler is aborted. FIELDS: postStart <Object> 支持啟動后 PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks preStop <Object>終止前 PreStop is called immediately before a container is terminated due to an API request or management event such as liveness probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod's termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod's termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks [root@www TestYaml]# kubectl explain pods.spec.containers.lifecycle.postStart KIND: Pod VERSION: v1 RESOURCE: postStart <Object> DESCRIPTION: PostStart is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks Handler defines a specific action that should be taken FIELDS: exec <Object> One and only one of the following should be specified. Exec specifies the action to take. httpGet <Object> HTTPGet specifies the http request to perform. tcpSocket <Object> TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported [root@www TestYaml]# [root@www TestYaml]# kubectl explain pods.spec.containers.lifecycle.preStop KIND: Pod VERSION: v1 RESOURCE: preStop <Object> 終止前 DESCRIPTION: PreStop is called immediately before a container is terminated due to an API request or management event such as liveness probe failure, preemption, resource contention, etc. The handler is not called if the container crashes or exits. The reason for termination is passed to the handler. The Pod's termination grace period countdown begins before the PreStop hooked is executed. Regardless of the outcome of the handler, the container will eventually terminate within the Pod's termination grace period. Other management of the container blocks until the hook completes or until the termination grace period is reached. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks Handler defines a specific action that should be taken FIELDS: exec <Object> 可以看到三種方式和上面的探針一樣,其功能也類似 One and only one of the following should be specified. Exec specifies the action to take. httpGet <Object> HTTPGet specifies the http request to perform. tcpSocket <Object> TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported
兩者都是容器的兩個極端點運行之前需要執行一些命令或者操作之后才能運行和終止容器,如果這些命令和操作執行失敗了,容器會終止並重啟,這個重啟就取決於重啟策略。