pod(一):Kubernetes(k8s)建立pod的兩種方式

2022-09-16 21:00:30

一.系統環境

伺服器版本 docker軟體版本 CPU架構
CentOS Linux release 7.4.1708 (Core) Docker version 20.10.12 x86_64

二.前言

docker可以建立容器,Kubernetes不能直接建立容器,Kubernetes建立的是pod,pod裡面包含了一個或者多個容器。

建立pod的前提是已經有一套可以正常執行的Kubernetes叢集,關於Kubernetes(k8s)叢集的安裝部署,可以檢視部落格《Centos7 安裝部署Kubernetes(k8s)叢集》https://www.cnblogs.com/renshengdezheli/p/16686769.html

三.pod

Pod 是可以在 Kubernetes 中建立和管理的、最小的可部署的計算單元。

Pod(就像在鯨魚莢或者豌豆莢中)是一組(一個或多個) 容器; 這些容器共用儲存、網路、以及怎樣執行這些容器的宣告。 Pod 中的內容總是並置(colocated)的並且一同排程,在共用的上下文中執行。 Pod 所建模的是特定於應用的 「邏輯主機」,其中包含一個或多個應用容器, 這些容器相對緊密地耦合在一起。 在非雲環境中,在相同的物理機或虛擬機器器上執行的應用類似於在同一邏輯主機上執行的雲應用。

除了應用容器,Pod 還可以包含在 Pod 啟動期間執行的 Init 容器。 你也可以在叢集中支援臨時性容器 的情況下,為偵錯的目的注入臨時性容器。

pod裡面有一個或者多個容器,常見的容器有docker容器,containerd容器,除了 Docker 之外,Kubernetes 支援 很多其他容器執行時, Docker 是最有名的容器執行時, 使用 Docker 的術語來描述 Pod 會很有幫助。

Pod 的共用上下文包括一組 Linux 名稱空間、控制組(cgroup)和可能一些其他的隔離方面, 即用來隔離 Docker 容器的技術。 在 Pod 的上下文中,每個獨立的應用可能會進一步實施隔離。

就 Docker 概念的術語而言,Pod 類似於共用名稱空間和檔案系統卷的一組 Docker 容器。

四.建立pod

4.1 環境介紹

Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點

伺服器 作業系統版本 CPU架構 程序 功能描述
k8scloude1/192.168.110.130 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico k8s master節點
k8scloude2/192.168.110.129 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點
k8scloude3/192.168.110.128 CentOS Linux release 7.4.1708 (Core) x86_64 docker,kubelet,kube-proxy,calico k8s worker節點

Kubernetes建立pod一般有兩種方式:

  1. 使用命令列的方式建立pod;
  2. 使用yaml檔案建立pod

4.2 使用命令列的方式建立pod

建立pod的命令為kubectl run,kubectl建立pod的幫助可以檢視網頁版,網頁版地址為:https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands

檢視kubectl run建立pod的幫助

[root@k8scloude1 ~]# kubectl run --help
Create and run a particular image in a pod.

Examples:
  # Start a nginx pod.
  kubectl run nginx --image=nginx
  
  # Start a hazelcast pod and let the container expose port 5701.
  kubectl run hazelcast --image=hazelcast/hazelcast --port=5701
 ......
Usage:
  kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=server|client] [--overrides=inline-json]
[--command] -- [COMMAND] [args...] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

首先拉取我們需要的映象,先在worker節點拉取nginx映象

[root@k8scloude2 ~]# docker pull nginx

[root@k8scloude3 ~]# docker pull nginx

4.2.1 建立最簡單的pod

使用nginx映象建立一個pod

#nginx為pod名字     --image=nginx表示使用Nginx映象
[root@k8scloude1 pod]# kubectl run nginx --image=nginx
pod/nginx created

檢視pod,STATUS為Running就表示pod建立成功

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS              RESTARTS   AGE
nginx   0/1     ContainerCreating   0          6s

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          54s

刪除pod

[root@k8scloude1 pod]# kubectl delete pod nginx
pod "nginx" deleted

4.2.2 建立pod,指定映象下載策略

使用nginx映象建立一個pod,映象的下載策略為IfNotPresent本地沒有才下載映象

映象的下載策略:Always:每次都下載最新的映象;Never:只使用本地映象,從不下載,IfNotPresent:本地沒有才下載映象 預設值為:Always

#nginx為pod名字     --image=nginx表示使用Nginx映象  --image-pull-policy=IfNotPresent表示映象下載策略為IfNotPresent本地沒有才下載映象
[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent
pod/nginx created

[root@k8scloude1 pod]# kubectl get pod
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          5s

#刪除pod
[root@k8scloude1 pod]# kubectl delete pod nginx
pod "nginx" deleted

注意:kubectl delete pod nginx會有點慢,加了--force 強制刪除pod,刪除pod會快很多

[root@k8scloude1 pod]# kubectl delete pod nginx --force
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "nginx" force deleted

4.2.3 建立pod,指定環境變數和標籤

檢視pod標籤的幫助

[root@k8scloude1 ~]# kubectl run --help | grep labels
  # Start a hazelcast pod and set labels "app=hazelcast" and "env=prod" in the container.
  kubectl run hazelcast --image=hazelcast/hazelcast --labels="app=hazelcast,env=prod"
  -l, --labels='': Comma separated labels to apply to the pod(s). Will override previous values.

建立pod,指定環境變數和標籤

#nginx為pod名字     --image=nginx表示使用Nginx映象  --image-pull-policy=IfNotPresent表示映象下載策略為IfNotPresent本地沒有才下載映象   --env:設定變數xx=1,yy=2     --labels設定標籤,給pod打上「xx=1,yy=2」的標籤
[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --env "xx=1" --env "yy=2" --labels="xx=1,yy=2"
pod/nginx created

#檢視pod
[root@k8scloude1 pod]# kubectl get pod -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          20s   10.244.112.136   k8scloude2   <none>           <none>

進入到pod裡,可以看到變數xx,yy

[root@k8scloude1 pod]# kubectl exec -it nginx -- bash
root@nginx:/# echo $xx
1
root@nginx:/# echo $yy
2
root@nginx:/# exit
exit

檢視pod的標籤,--show-labels引數顯示標籤

[root@k8scloude1 pod]# kubectl get pod -o wide --show-labels
NAME    READY   STATUS    RESTARTS   AGE     IP               NODE         NOMINATED NODE   READINESS GATES   LABELS
nginx   1/1     Running   0          4m59s   10.244.112.136   k8scloude2   <none>           <none>            xx=1,yy=2

4.3 使用yaml檔案的方式建立pod

4.3.1 yaml檔案概述

YAML是"YAML Ain’t a Markup Language"(YAML不是一種標示語言)的遞迴縮寫。YAML的意思其實是:「Yet Another Markup Language」(仍是一種標示語言)。主要強調這種語言是以資料為中心,而不是以標示語言為重心,例如像xml語言就會使用大量的標記。

YAML是一個可讀性高,易於理解,用來表達資料序列化的格式。它的語法和其他高階語言類似,並且可以簡單表達清單(陣列)、雜湊表,標量等資料形態。它使用空白符號縮排和大量依賴外觀的特色,特別適合用來表達或編輯資料結構、各種組態檔等。YAML的組態檔字尾為 .yaml。

  • yaml檔案基本語法:
    YAML使用可列印的Unicode字元,可使用UTF-8或UTF-16。

  • 資料結構採用鍵值對的形式,即 鍵名稱: 值,注意冒號後面要有空格。

  • 每個清單(陣列)成員以單行表示,並用短槓+空白(- )起始。或使用方括號([]),並用逗號+空白(, )分開成員。

  • 每個雜湊表的成員用冒號+空白(: )分開鍵值和內容。或使用大括號({ }),並用逗號+空白(, )分開。

  • 字串值一般不使用引號,必要時可使用,使用雙引號表示字串時,會跳脫字串中的特殊字元(例如\n)。使用單引號時不會跳脫字串中的特殊字元。

  • 大小寫敏感

  • 使用縮排表示層級關係,縮排不允許使用tab,只允許空格,因為有可能在不同系統下tab長度不一樣

  • 縮排的空格數可以任意,只要相同層級的元素左對齊即可

  • 在單一檔案中,可用連續三個連字號(---)區分多個檔案。還有選擇性的連續三個點號(…)用來表示檔案結尾。

  • '#'表示註釋,可以出現在一行中的任何位置,單行註釋

  • 在使用逗號及冒號時,後面都必須接一個空白字元,所以可以在字串或數值中自由加入分隔符號(例如:5,280或http://www.wikipedia.org)而不需要使用引號。

接下里使用yaml檔案的方式建立pod

4.3.2 使用yaml檔案的方式建立pod

--dry-run 模擬執行,並不會真的建立一個pod , --dry-run=client輸出資訊少 ,--dry-run=server輸出資訊多, -o yaml以yaml檔案的格式輸出

--dry-run=server輸出資訊如下:內容很多

#nginx為pod名字     --image=nginx表示使用Nginx映象  --image-pull-policy=IfNotPresent表示映象下載策略為IfNotPresent本地沒有才下載映象
[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --dry-run=server -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2022-01-12T07:51:11Z"
  labels:
    run: nginx
  name: nginx
  namespace: pod
  uid: afa40310-3efd-4d9f-8337-8e1db955c6f7
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-w56gz
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  preemptionPolicy: PreemptLowerPriority
  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: kube-api-access-w56gz
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
status:
  phase: Pending
  qosClass: BestEffort

--dry-run=client輸出資訊如下:輸出內容恰到好處

[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

生成建立pod的yaml檔案

[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml >nginx.yaml

yaml檔案裡有很多變數,可以使用kubectl explain檢視yaml檔案每個欄位的含義

# kubectl explain pods檢視一級欄位有哪些,每個的含義
[root@k8scloude1 ~]# kubectl explain pods
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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#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

   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

檢視一級欄位下包含了哪些欄位,對某個欄位不瞭解,先使用kubectl explain檢視

[root@k8scloude1 ~]# kubectl explain pod.spec

[root@k8scloude1 ~]# kubectl explain pods.spec.containers

[root@k8scloude1 ~]# kubectl explain pods.spec.containers.ports

容器containers裡也可以自定義變數,定義變數的時候:變數的值如果是數位,需要加「」

[root@k8scloude1 pod]# vim nginx.yaml 

#kind: Pod表示資源型別為Pod   labels指定pod標籤   metadata下面的name指定pod名字   containers下面全是容器的定義   
#image指定映象名字  imagePullPolicy指定映象下載策略   containers下面的name指定容器名
#resources指定容器資源(CPU,記憶體等)   env指定容器裡的環境變數   dnsPolicy指定DNS策略
#restartPolicy容器重啟策略
[root@k8scloude1 pod]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
    env:
    - name: xx
      value: "12"
    - name: yy
      value: "21"
    - name: zz
      value: hello
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

kubectl apply -f 應用組態檔,建立pod

[root@k8scloude1 pod]# kubectl apply -f nginx.yaml 
pod/nginx created

[root@k8scloude1 pod]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          26s

刪除pod

[root@k8scloude1 pod]# kubectl delete -f nginx.yaml 
pod "nginx" deleted

[root@k8scloude1 pod]# kubectl get pods
No resources found in pod namespace.

定義一個pod指明容器的埠,containerPort: 80 只是告知外界nginx這個pod使用80埠,真正要修改埠需要修改映象

[root@k8scloude1 pod]# vim nginx.yaml 

#kind: Pod表示資源型別為Pod   labels指定pod標籤   metadata下面的name指定pod名字   containers下面全是容器的定義   
#image指定映象名字  imagePullPolicy指定映象下載策略   containers下面的name指定容器名
#resources指定容器資源(CPU,記憶體等)   env指定容器裡的環境變數   dnsPolicy指定DNS策略
#restartPolicy容器重啟策略    ports指定容器埠
[root@k8scloude1 pod]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
    ports:
    - name: http
      containerPort: 80
      protocol: TCP
    env:
    - name: xx
      value: "12"
    - name: yy
      value: "21"
    - name: zz
      value: hello
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

建立pod

[root@k8scloude1 pod]# kubectl apply -f nginx.yaml 
pod/nginx created

[root@k8scloude1 pod]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          3s

強制刪除pod

[root@k8scloude1 pod]# kubectl delete pod nginx --force 
warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.
pod "nginx" force deleted

4.3.3 yaml檔案裡的字典和列表

先生成一個yaml檔案

[root@k8scloude1 pod]# kubectl run nginx --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

我們注意到,有的欄位前面有- ,有的沒有- ,沒有-的是字典,字典裡不能有重複變數,有-的是列表,列表裡的每個物件都是一個匿名字典,在列表中,物件的第一個欄位要加-

例如:當pod裡有多個容器的時候,containers可以定義多個,每個容器是一個物件,每個容器的第一個變數就加-

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: nginx
  name: nginx
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: nginx
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always

status: {}

4.3.4 檢視不同型別的apiVersion

不同的Kubernetes資源型別,apiVersion是不一樣的,Pod的apiVersion為v1

kubectl api-versions 檢視所有的apiVersion

[root@k8scloude1 ~]# kubectl api-versions 
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apps/v1
authentication.k8s.io/v1
authentication.k8s.io/v1beta1
authorization.k8s.io/v1
authorization.k8s.io/v1beta1
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
batch/v1
batch/v1beta1
certificates.k8s.io/v1
certificates.k8s.io/v1beta1
coordination.k8s.io/v1
coordination.k8s.io/v1beta1
crd.projectcalico.org/v1
discovery.k8s.io/v1
discovery.k8s.io/v1beta1
events.k8s.io/v1
events.k8s.io/v1beta1
extensions/v1beta1
flowcontrol.apiserver.k8s.io/v1beta1
metrics.k8s.io/v1beta1
networking.k8s.io/v1
networking.k8s.io/v1beta1
node.k8s.io/v1
node.k8s.io/v1beta1
policy/v1
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

4.3.5 使用同一個yaml檔案建立多個pod

生成yaml檔案

[root@k8scloude1 pod]# kubectl run pod1 --image=nginx --image-pull-policy=IfNotPresent --dry-run=client -o yaml >pod1.yaml

使用同一個yaml檔案建立2個pod

[root@k8scloude1 pod]# sed 's/pod1/pod2/' pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod2
  name: pod2
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod2
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

[root@k8scloude1 pod]# sed 's/pod1/pod2/' pod1.yaml | kubectl apply -f -
pod/pod2 created

[root@k8scloude1 pod]# sed 's/pod1/pod3/' pod1.yaml | kubectl apply -f -
pod/pod3 created

[root@k8scloude1 pod]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
pod2    1/1     Running   0          30s
pod3    1/1     Running   0          9s

[root@k8scloude1 pod]# ls
pod1.yaml