k8s核心資源之Pod概念及入門使用講解&&資源清單yaml文件內容講解與編寫(三)

1、 k8s核心資源之Pod概念及入門使用

1.1 什麼是Pod?

官方文檔:https://kubernetes.io/docs/concepts/workloads/pods/

Pod是Kubernetes中的最小調度單元,k8s是通過定義一個Pod的資源,然後在Pod裏面運行容器,容器需要指定一個鏡像,這樣就可以用來運行具體的服務。一個Pod封裝一個容器(也可以封裝多個容器),Pod裏的容器共享存儲、網絡等。也就是說,應該把整個pod看作虛擬機,然後每個容器相當於運行在虛擬機的進程。

image
Pod是需要調度到k8s集羣的工作節點來運行的,具體調度到哪個節點,是根據scheduler調度器實現的。

白話解釋:
可以把pod看成是一個“豌豆莢”,裏面有很多“豆子”(容器)。一個豌豆莢裏的豆子,它們吸收着共同的營養成分、肥料、水分等,Pod和容器的關係也是一樣,Pod裏面的容器共享pod的網絡、存儲等。
image

pod相當於一個邏輯主機--比方說我們想要部署一個tomcat應用,如果不用容器,我們可能會部署到物理機、虛擬機或者雲主機上,那麼出現k8s之後,我們就可以定義一個pod資源,在pod裏定義一個把tomcat容器,所以pod充當的是一個邏輯主機的角色。

1.2 Pod如何管理多個容器?

image

Pod中可以同時運行多個容器。同一個Pod中的容器會自動的分配到同一個 node 上。同一個Pod中的容器共享資源、網絡環境,它們總是被同時調度,在一個Pod中同時運行多個容器是一種比較高級的用法,只有當你的容器需要緊密配合協作的時候才考慮用這種模式。例如,你有一個容器作爲web服務器運行,需要用到共享的volume,有另一個“sidecar”容器來從遠端獲取資源更新這些文件。

一些Pod有init容器和應用容器。 在應用程序容器啓動之前,運行初始化容器。

1.3 Pod網絡

Pod是有IP地址的,每個pod都被分配唯一的IP地址(IP地址是靠網絡插件calico、flannel、weave等分配的),POD中的容器共享網絡名稱空間,包括IP地址和網絡端口。 Pod內部的容器可以使用localhost相互通信。 Pod中的容器也可以通過網絡插件calico與其他節點的Pod通信。

1.4 Pod存儲

創建Pod的時候可以指定掛載的存儲卷。 POD中的所有容器都可以訪問共享卷,允許這些容器共享數據。 Pod只要掛載持久化數據卷,Pod重啓之後數據還是會存在的。

1.5 Pod工作方式

在K8s中,所有的資源都可以使用一個yaml文件來創建,創建Pod也可以使用yaml配置文件。或者使用kubectl run在命令行創建Pod(不常用)。

1.5.1 自主式Pod

① 所謂的自主式Pod,就是直接定義一個Pod資源,如下:yaml文件內容編寫在後面會有講解

[root@k8s-master1 kubenetes-han]# vim pod-tomcat.yaml
apiVersion: v1
kind: Pod
metadata:
  name: tomcat-test
  namespace: default
  labels:
    app:  tomcat
spec:
  containers:
  - name:  tomcat-java
    ports:
    - containerPort: 8080
    image: hxu/tomcat-8.5-jre8:v1
  imagePullPolicy: IfNotPresent

② 上傳鏡像到node節點,步驟省略
③ 更新資源清單文件yaml文件創建pod

[root@k8s-master1 kubenetes-han]# kubectl apply -f pod-tomcat.yaml 
pod/tomcat-test created
查看pod
[root@k8s-master1 kubenetes-han]# kubectl get pod
tomcat-test                   1/1     Running   0          5s

但是自主式Pod是存在一個問題的,假如我們不小心刪除了pod:

[root@k8s-master1 kubenetes-han]# kubectl delete pods tomcat-test
pod "tomcat-test" deleted

查看pod是否還在
kubectl get pods -l app=tomcat
結果是空,說明pod已經被刪除了
通過上面可以看到,如果直接定義一個Pod資源,那Pod被刪除,就徹底被刪除了,不會再創建一個新的Pod,這在生產環境還是具有非常大風險的,所以今後我們接觸的Pod,都是控制器管理的。

1.5.2 控制器管理的Pod

常見的管理Pod的控制器:Replicaset、Deployment、Job、CronJob、Daemonset、Statefulset。
控制器管理的Pod可以確保Pod始終維持在指定的副本數運行。
如,通過Deployment管理Pod

① 更新資源清單文件

#更新資源清單文件
[root@k8s-master1 kubenetes-han]#  kubectl apply -f nginx-deploy.yaml
#查看Deployment
[root@k8s-master1 kubenetes-han]# kubectl get deploy -l app=nginx-deploy
NAME         READY   UP-TO-DATE   AVAILABLE   AGE
nginx-test   2/2     2            2           8d
[root@k8s-master1 kubenetes-han]# kubectl get rs -l app=nginx
NAME                    DESIRED   CURRENT   READY   AGE
nginx-test-57f9f5b6d7   2         2         2       8d
#查看pod
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide -l app=nginx
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-test-57f9f5b6d7-dqm8h   1/1     Running   0          8d    10.244.1.17   k8s-node1   <none>           <none>
nginx-test-57f9f5b6d7-fxsw5   1/1     Running   0          8d    10.244.1.16   k8s-node1   <none>           <none>
#刪除nginx-test-57f9f5b6d7-dqm8h這個pod
[root@k8s-master1 kubenetes-han]# kubectl delete pods nginx-test-57f9f5b6d7-dqm8h
pod "nginx-test-57f9f5b6d7-dqm8h" deleted
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide -l app=nginx
NAME                          READY   STATUS    RESTARTS   AGE   IP            NODE        NOMINATED NODE   READINESS GATES
nginx-test-57f9f5b6d7-8zt7x   1/1     Running   0          16s   10.244.1.19   k8s-node1   <none>           <none>
nginx-test-57f9f5b6d7-fxsw5   1/1     Running   0          8d    10.244.1.16   k8s-node1   <none>           <none>
#發現重新創建一個新的pod是nginx-test-57f9f5b6d7-8zt7x

通過上面可以發現通過deployment管理的pod,可以確保pod始終維持在指定副本數量

1.6 創建Pod流程

image
Pod是Kubernetes中最基本的部署調度單元,可以包含container,邏輯上表示某種應用的一個實例。例如一個web站點應用由前端、後端及數據庫構建而成,這三個組件將運行在各自的容器中,那麼我們可以創建包含三個container的pod
創建pod的詳細流程:
image

第一步:
客戶端提交創建Pod的請求,可以通過調用API Server的Rest API接口,也可以通過kubectl命令行工具。如kubectl apply -f filename.yaml(資源清單文件)
第二步:
apiserver接收到pod創建請求後,會將yaml中的屬性信息(metadata)寫入etcd。
第三步:
apiserver觸發watch機制準備創建pod,信息轉發給調度器scheduler,調度器使用調度算法選擇node,調度器將node信息給apiserver,apiserver將綁定的node信息寫入etcd
調度器用一組規則過濾掉不符合要求的主機。比如Pod指定了所需要的資源量,那麼可用資源比Pod需要的資源量少的主機會被過濾掉。
scheduler 查看 k8s api ,類似於通知機制。
首先判斷:pod.spec.Node == null?
若爲null,表示這個Pod請求是新來的,需要創建;因此先進行調度計算,找到最“閒”的node。
然後將信息在etcd數據庫中更新分配結果:pod.spec.Node = nodeA (設置一個具體的節點)
ps:同樣上述操作的各種信息也要寫到etcd數據庫中中
第四步:
apiserver又通過watch機制,調用kubelet,指定pod信息,調用Docker API創建並啓動pod內的容器。
第五步:
創建完成之後反饋給kubelet, kubelet又將pod的狀態信息給apiserver,
apiserver又將pod的狀態信息寫入etcd。

2、Pod資源清單yaml文件內容詳細解讀

apiVersion: v1       #版本號,例如v1
kind: Pod       #資源類型,如Pod
metadata:       #元數據
  name: string       # Pod名字
  namespace: string    # Pod所屬的命名空間
  labels:      #自定義標籤
    - name: string     #自定義標籤名字
  annotations:       #自定義註釋列表
    - name: string
spec:         # Pod中容器的詳細定義
  containers:      # Pod中容器列表
  - name: string     #容器名稱
    image: string    #容器的鏡像名稱
    imagePullPolicy: [Always | Never | IfNotPresent] #獲取鏡像的策略 Alawys表示下載鏡像 IfnotPresent表示優先使用本地鏡像,否則下載鏡像,Nerver表示僅使用本地鏡像
    command: [string]    #容器的啓動命令列表,如不指定,使用打包時使用的啓動命令
    args: [string]     #容器的啓動命令參數列表
    workingDir: string     #容器的工作目錄
    volumeMounts:    #掛載到容器內部的存儲卷配置
    - name: string     #引用pod定義的共享存儲卷的名稱,需用volumes[]部分定義的的卷名
      mountPath: string    #存儲卷在容器內mount的絕對路徑,應少於512字符
      readOnly: boolean    #是否爲只讀模式
    ports:       #需要暴露的端口庫號
    - name: string     #端口號名稱
      containerPort: int   #容器需要監聽的端口號
      hostPort: int    #容器所在主機需要監聽的端口號,默認與Container相同
      protocol: string     #端口協議,支持TCP和UDP,默認TCP
    env:       #容器運行前需設置的環境變量列表
    - name: string     #環境變量名稱
      value: string    #環境變量的值
    resources:       #資源限制和請求的設置
      limits:      #資源限制的設置
        cpu: string    #cpu的限制,單位爲core數
        memory: string     #內存限制,單位可以爲Mib/Gib
      requests:      #資源請求的設置
        cpu: string    #cpu請求,容器啓動的初始可用數量
        memory: string     #內存請求,容器啓動的初始可用內存
    livenessProbe:     #對Pod內個容器健康檢查的設置,當探測無響應幾次後將自動重啓該容器,檢查方法有exec、httpGet和tcpSocket,對一個容器只需設置其中一種方法即可
      exec:      #對Pod容器內檢查方式設置爲exec方式
        command: [string]  #exec方式需要制定的命令或腳本
      httpGet:       #對Pod內個容器健康檢查方法設置爲HttpGet,需要制定Path、port
        path: string
        port: number
        host: string
        scheme: string
        HttpHeaders:
        - name: string
          value: string
      tcpSocket:     #對Pod內個容器健康檢查方式設置爲tcpSocket方式
         port: number
       initialDelaySeconds: 0  #容器啓動完成後首次探測的時間,單位爲秒
       timeoutSeconds: 0   #對容器健康檢查探測等待響應的超時時間,單位秒,默認1秒
       periodSeconds: 0    #對容器監控檢查的定期探測時間設置,單位秒,默認10秒一次
       successThreshold: 0
       failureThreshold: 0
       securityContext:
         privileged:false
    restartPolicy: [Always | Never | OnFailure]#Pod的重啓策略,Always表示一旦不管以何種方式終止運行,kubelet都將重啓,OnFailure表示只有Pod以非0退出碼退出才重啓,Nerver表示不再重啓該Pod
    nodeSelector: obeject  #設置NodeSelector表示將該Pod調度到包含這個label的node上,以key:value的格式指定
    imagePullSecrets:    #Pull鏡像時使用的secret名稱,以key:secretkey格式指定
    - name: string
    hostNetwork:false      #是否使用主機網絡模式,默認爲false,如果設置爲true,表示使用宿主機網絡
    volumes:       #在該pod上定義共享存儲卷列表
    - name: string     #共享存儲卷名稱 (volumes類型有很多種)
      emptyDir: {}     #類型爲emtyDir的存儲卷,與Pod同生命週期的一個臨時目錄。爲空值
      hostPath: string     #類型爲hostPath的存儲卷,表示掛載Pod所在宿主機的目錄
        path: string     #Pod所在宿主機的目錄,將被用於同期中mount的目錄
      secret:      #類型爲secret的存儲卷,掛載集羣與定義的secre對象到容器內部
        scretname: string  
        items:     
        - key: string
          path: string
      configMap:     #類型爲configMap的存儲卷,掛載預定義的configMap對象到容器內部
        name: string
        items:
        - key: string
          path: string

3、如何編寫資源清單YAML文件?

示例:

# vim pod-tomcat.yaml
apiVersion: v1  #api版本
kind: Pod       #創建的資源
metadata:    
  name: tomcat-test  #Pod的名字
  namespace: default   #Pod所在的名稱空間
  labels:
    app:  tomcat     #Pod具有的標籤
spec:
  containers:
  - name:  tomcat-java   #Pod裏容器的名字
    ports:
    - containerPort: 8080  #容器暴露的端口
    image: hxu/tomcat-8.5-jre8:v1  #容器使用的鏡像
  imagePullPolicy: IfNotPresent    #鏡像拉取策略

#更新資源清單文件
# kubectl apply -f pod-tomcat.yaml 

# Pod資源清單編寫技巧
通過kubectl explain 查看定義Pod資源包含哪些字段。
# kubectl explain pod
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.
[Pod是可以在主機上運行的容器的集合。此資源是由客戶端創建並安排到主機上。]

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/sig-architecture/api-conventions.md#resources
[APIVersion定義了對象,代表了一個版本。]
   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/sig-architecture/api-conventions.md#types-kinds
[Kind是字符串類型的值,代表了要創建的資源。服務器可以從客戶端提交的請求推斷出這個資源。]
   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
[metadata是對象,定義元數據屬性信息的]
   spec	<Object>
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
[spec制定了定義Pod的規格,裏面包含容器的信息]
   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/sig-architecture/api-conventions.md#spec-and-status
[status表示狀態,這個不可以修改,定義pod的時候也不需要定義這個字段]

#查看pod.metadata字段如何定義
# kubectl explain pod.metadata
KIND:     Pod
VERSION:  v1
RESOURCE: metadata <Object>

# metadata是對象<Object>,下面可以有多個字段

DESCRIPTION:
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/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>
     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
# annotations是註解,map類型表示對應的值是key-value鍵值對,<string,string>表示 key和value都是String類型的
"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}
用Annotation來記錄的信息包括:
build信息、release信息、Docker鏡像信息等,例如時間戳、release id號、鏡像hash值、docker registry地址等;
日誌庫、監控庫、分析庫等資源庫的地址信息;
程序調試工具信息,例如工具名稱、版本號等;
團隊的聯繫信息,例如電話號碼、負責人名稱、網址等。

   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.
#對象所屬羣集的名稱。這是用來區分不同集羣中具有相同名稱和命名空間的資源。此字段現在未設置在任何位置,apiserver將忽略它,如果設置了就使用設置的值

   creationTimestamp	<string>
   deletionGracePeriodSeconds	<integer>
   deletionTimestamp	<string>
   finalizers	<[]string>
   generateName	<string>
   generation	<integer>
   labels	<map[string]string> #創建的資源具有的標籤
Map of string keys and values that can be used to organize and categorize
     (scope and select) objects. May match selectors of replication controllers
     and services. More info: http://kubernetes.io/docs/user-guide/labels
#labels是標籤,labels是map類型,map類型表示對應的值是key-value鍵值對,<string,string>表示 key和value都是String類型的
   managedFields	<[]Object>
   name	<string>           #創建的資源的名字
   namespace	<string>      #創建的資源所屬的名稱空間
Namespace defines the space within which each name must be unique. An empty
namespace is equivalent to the "default" namespace, but "default" is the
canonical representation. Not all objects are required to be scoped to a
namespace - the value of this field for those objects will be empty.
     Must be a DNS_LABEL. Cannot be updated. More info:
     http://kubernetes.io/docs/user-guide/namespaces
# namespaces劃分了一個空間,在同一個namesace下的資源名字是唯一的,默認的名稱空間是default。
   ownerReferences	<[]Object>
   resourceVersion	<string>
   selfLink	<string>
   uid	<string>****

查看pod.spec字段如何定義

# kubectl explain pod.spec
KIND:     Pod
VERSION:  v1
RESOURCE: spec <Object>
DESCRIPTION:
     Specification of the desired behavior of the pod. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
     PodSpec is a description of a pod.
#Pod的spec字段是用來描述Pod的

FIELDS:
   activeDeadlineSeconds	<integer>
#表示Pod可以運行的最長時間,達到設置的值後,Pod會自動停止。
affinity	<Object>
  #定義親和性的
   automountServiceAccountToken	<boolean>
   containers	<[]Object> -required-
#containers是對象列表,用來定義容器的,是必須字段。對象列表 表示下面有很多對象,對象列表下面的內容用 - 連接。
   dnsConfig	<Object>
   dnsPolicy	<string>
   enableServiceLinks	<boolean>
   ephemeralContainers	<[]Object>
   hostAliases	<[]Object>
   hostIPC	<boolean>
   hostNetwork	<boolean>
   hostPID	<boolean>
   hostname	<string>
   imagePullSecrets	<[]Object>
   initContainers	<[]Object>
   nodeName	<string>
   nodeSelector	<map[string]string>
   overhead	<map[string]string>
   preemptionPolicy	<string>
   priority	<integer>
   priorityClassName	<string>
   readinessGates	<[]Object>
   restartPolicy	<string>
   runtimeClassName	<string>
   schedulerName	<string>
   securityContext	<Object>
   serviceAccount	<string>
   serviceAccountName	<string>
   setHostnameAsFQDN	<boolean>
   shareProcessNamespace	<boolean>
   subdomain	<string>
   terminationGracePeriodSeconds	<integer>
   tolerations	<[]Object>
   topologySpreadConstraints	<[]Object>
   volumes	<[]Object>

查看pod.spec.containers字段如何定義

# kubectl explain pod.spec.containers
KIND:     Pod
VERSION:  v1

RESOURCE: containers <[]Object>
DESCRIPTION:
     List of containers belonging to the pod. Containers cannot currently be
     added or removed. There must be at least one container in a Pod. Cannot be
     updated.
     A single application container that you want to run within a pod.
#container是定義在pod裏面的,一個pod至少要有一個容器。

FIELDS:
   args	<[]string>
   command	<[]string>
   env	<[]Object>
   envFrom	<[]Object>
   image	<string>
#image是用來指定容器需要的鏡像的
   imagePullPolicy	<string>
#鏡像拉取策略,pod是要調度到node節點的,那pod啓動需要鏡像,可以根據這個字段設置鏡像拉取策略,支持如下三種:
Always:不管本地是否存在鏡像,都要重新拉取鏡像
Never: 從不拉取鏡像
IfNotPresent:如果本地存在,使用本地的鏡像,本地不存在,從官方拉取鏡像

   lifecycle	<Object>
   livenessProbe	<Object>
   name	<string> -required-
#name是必須字段,用來指定容器名字的
   ports	<[]Object>
#port是端口,屬於對象列表
   readinessProbe	<Object>
   resources	<Object>
   securityContext	<Object>
   startupProbe	<Object>
   stdin	<boolean>
   stdinOnce	<boolean>
   terminationMessagePath	<string>
   terminationMessagePolicy	<string>
   tty	<boolean>
   volumeDevices	<[]Object>
   volumeMounts	<[]Object>
   workingDir	<string>

查看pod.spec.container.ports字段如何定義

# kubectl explain pod.spec.containers.ports
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.
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.
#containerPort是必須字段, pod中的容器需要暴露的端口。

   hostIP	<string>
     What host IP to bind the external port to.
#將容器中的服務暴露到宿主機的端口上時,可以指定綁定的宿主機 IP。
   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".

通過資源清單文件創建第一個Pod(如上文的1.5.1章節)

#查看pod日誌
kubectl logs pod-first

#查看pod裏指定容器的日誌
kubectl logs pod-first  -c tomcat-first

#進入到剛纔創建的pod,剛纔創建的pod名字是web
kubectl exec -it pod-first  -- /bin/bash

#假如pod裏有多個容器,進入到pod裏的指定容器,按如下命令:
kubectl exec -it pod-first  -c  tomcat-first -- /bin/bash 

我們上面創建的pod是一個自主式pod,也就是通過pod創建一個應用程序,如果pod出現故障停掉,那麼我們通過pod部署的應用也就會停掉,不安全, 還有一種控制器管理的pod,通過控制器創建pod,可以對pod的生命週期做管理,可以定義pod的副本數,如果有一個pod意外停掉,那麼會自動起來一個pod替代之前的pod,之後會講解pod的控制器

通過kubectl run創建Pod

kubectl run tomcat --image=hxu/tomcat-8.5-jre8:v1  --image-pull-policy='IfNotPresent'  --port=8080
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章