Docker 與 K8S學習筆記(十八)—— Pod的使用

阿拉懶神燈發表於2022-01-21

Pod 是一組緊密關聯的容器集合,它們共享IPC、Network和UTS namespace,是 Kubernetes 排程的基本單元。Pod 的設計理念是支援多個容器在一個 Pod 中共享網路和檔案系統,可以通過程式間通訊和檔案共享這種簡單高效的方式組合完成服務。

一、Pod的定義

這裡還是以我們之前做的webapp為例定義一個Pod,這是一個最簡單的Pod定義

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  containers:
  - name: webapp
    image: 172.16.194.135:5000/webapp:latest
    ports:
    - containerPort: 5000

關於Pod的定義比較重要的就是kind、spec.containers,kind就是定義資源型別、在spec.containers中主要定義容器所使用的映象,這裡可以定義多個容器。

 

二、Pod的基本使用

在使用Pod前我們需要注意,在Kubernetes中對於長時間執行的容器的要求是:其主程式需要一直在前臺執行。如果主程式執行在後臺,則Kubernetes會認為Pod執行結束,將會銷燬Pod。以webapp映象為例,它的Dockerfile如下:

FROM java:8
WORKDIR /opt/soft/
EXPOSE 4567
COPY webapp-1.0-SNAPSHOT.jar /opt/soft/webapp.jar
ENTRYPOINT ["java", "-jar", "/opt/soft/webapp.jar"]

接下來,我們嘗試一下Pod中多容器的場景,我們的Pod包含兩個容器:webapp和busybox,Pod定義如下:

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  containers:
  - name: webapp
    image: 172.16.194.135:5000/webapp:1.0
    ports:
    - containerPort: 5000
  - name: busybox
    image: busybox
    command: ["sh", "-c", "top"]

注意:busybox容器中我們定義了啟動命令top,這樣做就是為了確保busybox容器始終在前臺執行top命令,避免容器直接被銷燬。

我們建立Pod,並通過describe可以清楚看到這兩個容器的建立過程:

$ sudo kubectl create -f webapp_pod.yaml
pod/webapp created
$ sudo kubectl describe pod webapp
Name:         webapp
Namespace:    default
Priority:     0
Node:         ayato/172.16.194.135
Start Time:   Sat, 08 Jan 2022 05:49:38 +0000
Labels:       app=webapp
Annotations:  <none>
Status:       Running
IP:           172.17.0.6
IPs:
  IP:  172.17.0.6
Containers:
  webapp:
    Container ID:   docker://9c68ef7019126b65e2feba5d4d69e55997a9e573ce585b0bbb6a7cfe2fe20b31
    Image:          172.16.194.135:5000/webapp:1.0
    Image ID:       docker-pullable://172.16.194.135:5000/webapp@sha256:df3a447a013ada0642dec67bb31976f42f1a0699a68873d0452f514fa24e5c77
    Port:           5000/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 08 Jan 2022 05:49:40 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-pcr2h (ro)
  busybox:
    Container ID:  docker://0dfd00b5fa8e419bfe0b4a43595c83cb1d4986980914865ae3371e1724c7f568
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
      -c
      top
    State:          Running
      Started:      Sat, 08 Jan 2022 05:49:45 +0000
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-pcr2h (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-pcr2h:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-pcr2h
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m50s  default-scheduler  Successfully assigned default/webapp to ayato
  Normal  Pulled     3m49s  kubelet            Container image "172.16.194.135:5000/webapp:1.0" already present on machine
  Normal  Created    3m48s  kubelet            Created container webapp
  Normal  Started    3m48s  kubelet            Started container webapp
  Normal  Pulling    3m48s  kubelet            Pulling image "busybox"
  Normal  Pulled     3m44s  kubelet            Successfully pulled image "busybox" in 4.516692787s
  Normal  Created    3m44s  kubelet            Created container busybox
  Normal  Started    3m43s  kubelet            Started container busybox

我們之前說過同一個Pod中的容器共享網路,也就是說我們在busybox容器中可以通過localhost訪問webapp的介面,我們嘗試一下:

$ sudo kubectl exec -it webapp -c busybox /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # wget http://localhost:4567/api/hello
Connecting to localhost:4567 (127.0.0.1:4567)
saving to 'hello'
hello                100% |******************************************************************************************|    15  0:00:00 ETA
'hello' saved
/ # cat hello
Hello my friend/ #

 

三、Pod容器共享Volume

同一個Pod中的容器能夠共享Pod級別的Volume,Volume可以被定義為各種型別,多個容器分別進行掛載操作。我們還是以webapp和busybox為例,webapp向volume中寫log,busybox通過tail命令讀log,Pod定義如下:

apiVersion: v1
kind: Pod
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  containers:
  - name: webapp
    image: 172.16.194.135:5000/webapp:1.0
    ports:
    - containerPort: 5000
    volumeMounts:
    - name: webapp-logs
      mountPath: /tmp
  - name: busybox
    image: busybox
    command: ["sh", "-c", "tail -f /logs/log.out"]
    volumeMounts:
    - name: webapp-logs
      mountPath: /logs
  volumes:
  - name: webapp-logs
    emptyDir: {}

我們通過Pod定義中可以看到:我們設定了一個Volume,名稱為webapp-logs,type為emptyDir。容器webapp將Volume掛載到/tmp目錄,因為webapp配置了logback並會向/tmp中寫日誌。容器busybox將Volume掛載到/logs目錄,並通過tail命令持續讀日誌。我們啟動Pod,並使用kubectl logs命令從busybox中讀取tail的輸出:

$ sudo kubectl create -f webapp_pod.yaml
pod/webapp created
$ sudo kubectl logs webapp -c busybox
06:30:27.810 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] Starting TodoListApplication v1.0-SNAPSHOT using Java 1.8.0_111 on webapp with PID 1 (/opt/soft/webapp.jar started by root in /opt/soft)
06:30:27.821 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] No active profile set, falling back to default profiles: default
06:30:30.060 [INFO ] [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] Tomcat initialized with port(s): 4567 (http)
06:30:30.079 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Initializing ProtocolHandler ["http-nio-4567"]
06:30:30.088 [INFO ] [main] [org.apache.catalina.core.StandardService] Starting service [Tomcat]
06:30:30.089 [INFO ] [main] [org.apache.catalina.core.StandardEngine] Starting Servlet engine: [Apache Tomcat/9.0.41]
06:30:30.359 [INFO ] [main] [org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/]] Initializing Spring embedded WebApplicationContext
06:30:30.359 [INFO ] [main] [org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext] Root WebApplicationContext: initialization completed in 2407 ms
06:30:30.913 [INFO ] [main] [org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor] Initializing ExecutorService 'applicationTaskExecutor'
06:30:32.634 [WARN ] [main] [org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$DefaultTemplateResolverConfiguration] Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration)
06:30:32.956 [INFO ] [main] [org.apache.coyote.http11.Http11NioProtocol] Starting ProtocolHandler ["http-nio-4567"]
06:30:33.096 [INFO ] [main] [org.springframework.boot.web.embedded.tomcat.TomcatWebServer] Tomcat started on port(s): 4567 (http) with context path ''
06:30:33.131 [INFO ] [main] [org.demo.webapp.todolist.TodoListApplication] Started TodoListApplication in 6.387 seconds (JVM running for 7.205)

關於Volume的型別,有如下幾種:

1)emptyDir:emptyDir是在Pod分配到Node時建立的,它的初始內容為空,並且無須指定host上對應的目錄檔案,它是由Kubernetes自動分配的目錄,當Pod銷燬後,emptyDir中的資料也會被刪除。一般可用作臨時空間,存放應用程式臨時資料。

2)hostPath:將宿主機中的檔案或目錄掛載到Pod中。通常用於應用永久資料的儲存。

3)iscsi:將iSCSI儲存裝置上的目錄掛載到Pod中。

4)nfs:將NFS上的目錄掛載到Pod中。

5)glusterfs:將GlusterFS網路檔案系統的目錄掛載到Pod中。

6)rbd:將Ceph塊裝置共享儲存掛載到Pod中。

7)gitRepo:通過掛載一個空目錄,並從Git中克隆一個git倉庫供Pod使用。

8)configmap:將配置資料掛載為容器中的檔案。

9)secret:將Secret資料掛載為容器中的檔案。

相關文章