Pod定義與ConfigMap

Pod的做用

在k8s中pod是最小的管理單位,在一個pod中一般會包含一個或多個容器。
在每個Pod中都有一個特殊的Pause容器和一個或多個業務容器,Pause來源於pause-amd64鏡像,Pause容器在Pod中具備很是重要的做用:php

  • Pause容器做爲Pod容器的根容器,其本地於業務容器無關,它的狀態表明瞭整個pod的狀態。
  • Pod裏的多個業務容器共享Pause容器的IP,每一個Pod被分配一個獨立的IP地址,Pod中的每一個容器共享網絡命名空間,包括IP地址和網絡端口。Pod內的容器可使用localhost相互通訊。k8s支持底層網絡集羣內任意兩個Pod之間進行通訊。
  • Pod中的全部容器均可以訪問共享volumes,容許這些容器共享數據。volumes還用於Pod中的數據持久化,以防其中一個容器須要從新啓動而丟失數據。

    kubernetes 的對象定義通常都用YAML或JSON格式的文件,可使用這個網址驗證yaml語法:https://codebeautify.org/yaml-validator node

Pod的定義

Kubernetes中全部的資源對象均可以採用YAML或者JSON格式的文件來定義。
咱們能夠定義含有單個服務容器的pod,可是在另外一種場景中,當兩個服務應用爲緊耦合的關係時,應該將他們組合成一個總體對外提供服務,以下定義,將兩個容器打包爲一個pod:nginx

apiVersion: v1
kind: Pod
metadata: 
  name: redis-php
  labels:
    name: redis-php
spec:
  hostNetwork: true                        # 指定能夠經過宿主機訪問pod中的服務
  containers:
  - name: frontend
    image: kubeguide/guestbook-php-frontend:localredis
    ports:
    - containerPort: 80
    # 指定宿主機映射端口。在不與hostNetwork: true 同時使用時能夠指定任意端口,可是在某些使用CNI插件的狀況下可能不會生效。
    # 與hostNetwork使用的時候,只能與容器端口一致,且能夠省略,通常只在測試時使用。
      hostPort: 80                          
  - name: redis
    image: kubeguide/redis-master
    ports:
    - containerPort: 6379
      hostPort: 6379

執行此文件:web

kubectl create -f pod-test.yaml

查看pod信息,能夠查看到容器的建立過程(Event 事件信息):redis

kubectl  describe pod  redis-php

靜態Pod

靜態pod是僅僅存在於特定Node上的Pod。 它們不能經過API server進行管理,沒法與RC,Deployment或者DaemonSet進行關聯,而且kubelet也沒法對其進行健康檢查。
靜態Pod老是由kubelet建立,而且老是在kubelet所在的節點Node上運行。
建立靜態pod有兩種方式:docker

  • 配置文件方式
  • HTTP方式

配置文件方式

一、首先在特定的節點上建立目錄,並建立static-web.yaml的文件,此文件定義了靜態pod的信息:json

mkdir /etc/kubernetes.d/

cat /etc/kubernetes.d/static-web.yaml 

 apiVersion: v1
 kind: Pod
 metadata:
   name: static-web
   labels:
     name: static-web
 spec:
   containers:
     - name: static-web
       image: nginx:1.12.2
       ports:
         - name: web
           containerPort: 80
           protocol: TCP

二、修改kubelet啓動文件參數,添加--pod-manifest-path=/etc/kubernetes.d/, 並重啓kubelet。
三、Master節點上查看:api

# kubectl get pod
NAME                  READY     STATUS    RESTARTS   AGE
static-web-10.0.0.3   1/1       Running   0          40s

本地node節點上已經啓動:tomcat

docker ps|grep nginx

33620ea59551        4037a5562b03                             "nginx -g 'daemon ..."   5 minutes ago       Up 5 minutes                            k8s_static-web_static-web-10.0.0.3_default_3fcbc9dd218421884a0a557825af52d5_0

四、刪除此靜態pod,因爲是在node節點由kubelet建立的,因此在master上執行刪除並不會生效,須要到此node節點上刪除此文件便可:網絡

rm -f static-web.yaml

HTTP方式

使用HTTP的方式也須要修改對應node節點的kubelet配置參數--manifest-url=<URL>
Kubelet將按期的從參數 --manifest-url=<URL> 配置的地址下載文件,並將其解析爲 json/yaml 格式的 pod 描述。
它的工做原理與從 --pod-manifest-path=<directory> 中發現文件執行建立/更新靜態 pod 是同樣的,即,文件的每次更新都將應用到運行中的靜態 pod 中。

Pod共享Volume

Pod的Volume用於同一個pod中的多個容器數據共享。
Kubernetes Volume具備明確的生命週期-與pod相同。所以,Volume的生命週期比Pod中運行的任何容器要持久,在容器從新啓動時能夠保留數據,固然,當Pod被刪除不存在時,Volume也將消失。注意,Kubernetes支持許多類型的Volume,Pod能夠同時使用任意類型/數量的Volume。
內部實現中,一個Volume只是一個目錄,目錄中可能有一些數據,pod的容器能夠訪問這些數據。至於這個目錄是如何產生的、支持它的介質、其中的數據內容是什麼,這些都由使用的特定Volume類型來決定。在定義Pod時,須要指定對應的Volume。

本地存儲

  • emptyDir: 無需指定宿主機的對應目錄路徑,由Pod自動建立,Pod移除時數據會永久刪除,做爲容器間的共享目錄。上面的示例就是此格式的Volume。
cat pod-volume.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: app-logs
      mountPath: /usr/local/tomcat/logs       # 容器中的日誌目錄
  - name: logreader                           # 容器名稱,使用kubectl指定容器時須要使用此名稱,沒法使用容器ID
    image: busybox
    command: ["sh","-c","tail -f /logs/catalina*.log"]
    volumeMounts:
    - name: app-logs
      mountPath: /logs
  volumes:                                    # volume設定的具體信息
  - name: app-logs
    emptyDir: {}                              # volume的類型,emryDir的參數設置爲{}

這裏的示例是將tomcat容器的日誌目錄和logreader的log目錄共享,經過在logreader執行查看日誌的命令,就能夠在logreader中看到tomcat的啓動日誌。
查看日誌:

kubectl logs volume-pod -c logreader

也能夠直接登陸容器查看:

kubectl exec -it volume-pod -c tomcat sh

或者不登陸直接執行容器命令:

kubectl exec -it volume-pod -c logreader  ls /logs
 kubectl exec -it volume-pod -c tomcat ls /usr/local/tomcat/logs
  • hostPath: Pod掛載宿主機上的文件和目錄,可用於永久保存日誌,容器內部訪問宿主機數據,定義方式以下:
apiVersion: v1
kind: Pod
metadata:
  name: volume-pod
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: app-logs
      mountPath: /usr/local/tomcat/logs
  volumes:
  - name: app-logs
    hostPath:
      # 宿主機的本地目錄,須要事先建立,不然pod沒法啓動
      path: /logs
      # this field is optional
      type: Directory

當pod刪除時,數據依舊保存在宿主機目錄中。

網絡存儲

k8s 也支持網絡存儲如NFS,分佈式存儲GlusterFS,對象存儲Cephfs等,這裏就不具體介紹,例如使用ceph的yaml配置以下:

apiVersion: v1
kind: Pod
metadata:
  name: cephfs
spec:
  containers:
  - name: cephfs-rw
    image: kubernetes/pause
    volumeMounts:
    - mountPath: "/mnt/cephfs"
      name: cephfs
  volumes:
  - name: cephfs
    cephfs:
      monitors:
      - 10.16.154.78:6789
      - 10.16.154.82:6789
      - 10.16.154.83:6789
      # by default the path is /, but you can override and mount a specific path of the filesystem by using the path attribute
      # path: /some/path/in/side/cephfs 
      user: admin
      secretFile: "/etc/ceph/admin.secret"
      readOnly: true

ConfigMap

configMap資源提供了一種將配置數據注入到Pod中的方法。在應用中可使用這種方式來提供應用須要的配置信息。 存儲在ConfigMap對象中的數據能夠在configMap類型的卷中引用,而後由運行在Pod中的容器化應用程序使用。
當引用一個configMap對象時,你能夠簡單地在卷中提供它的名字來引用它。 您還能夠自定義用於ConfigMap中特定條目的路徑。
通常有以下用法:

  • 生成容器內的環境變量
  • 設置容器啓動命令的啓動參數(須要設置環境變量)
  • 以Volume的方式掛載爲容器內部的文件或目錄

    在使用configMap時,須要先建立configMap,而後再在其餘對象中引用。

通常建立configMap能夠經過兩種方式:

  • 經過yaml配置文件方式
  • 經過使用kubectl create configmap命令的方式建立

一、經過YAML文件建立ConfigMap資源對象

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-test
data: 
  apploglevel: info
  appdatadir: /var/data

與通常的yaml文件一致,data區域爲配置的參數區域。若是參數很複雜而且不少,使用這種方式並不方便管理和查看。

二、經過使用kubectl create configmap命令建立
命令格式:

kubectl create configmap <map-name> <data-source>

map-name: 自定義的configMap名稱
data-source: 指定的配置文件信息,能夠是文件或文件目錄。 不管是哪一種文件,最終都必須是鍵值對形式。

指定目錄建立

如在/tmp/configmap 有以下文件:

# ll

-rw-r--r-- 1 root root 157 Jun 15 17:19 game.properties
-rw-r--r-- 1 root root  83 Jun 15 17:26 ui.properties

# cat game.properties 
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30

# cat ui.properties 
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

建立cofigmap:

# kubectl create configmap game-config --from-file=/tmp/configmap/

查看configmap:

# kubectl describe configmaps game-config
Name:         game-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events:  <none>

將兩個配置文件內容融合在了一塊兒。也可使用yaml的格式輸出,這和自定義YAML的輸出是相同的:

# kubectl get configmaps game-config -o yaml
apiVersion: v1
data:
  game.properties: |-
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  creationTimestamp: 2018-06-15T09:29:39Z
  name: game-config
  namespace: default
  resourceVersion: "150723"
  selfLink: /api/v1/namespaces/default/configmaps/game-config
  uid: a079ab6c-707e-11e8-96f7-000c295f81fb
指定文件

同理,也可使用指定文件的方式:

# kubectl create configmap game-spec --from-file=/tmp/configmap/game.properties
指定鍵值對

也可直接在命令行經過鍵值對直接指定:

# kubectl create configmap  man-spec --from-literal=name=config.test --from-literal=value=test

# kubectl get configmap man-spec -o yaml
apiVersion: v1
data:
  name: config.test
  value: test
kind: ConfigMap
metadata:
  creationTimestamp: 2018-06-15T09:47:35Z
  name: man-spec
  namespace: default
  resourceVersion: "151795"
  selfLink: /api/v1/namespaces/default/configmaps/man-spec
  uid: 21b019cb-7081-11e8-96f7-000c295f81fb
指定環境變量文件

可使用--from-env-file 參數指定系統中環境變量文件,使用此參數時,指定文件有如下特色:

  • 文件包含列表類型的環境變量
  • 每一行都必須是 key=value 的格式
  • # 開頭的行爲註釋,將會被忽略
  • 空行將會被忽略
  • 引號將不會被特殊處理,它將會做爲configMap 值的一部分。

以下,使用環境變量文件,建立一個對應的confmap配置:

# 文件內容:
# cat game-env-file.properties 
enemies=aliens
lives=3
allowed="true"

# This comment and the empty line above it are ignored

# 建立ConfigMap
# kubectl create configmap game-env --from-env-file=/tmp/configmap/game-env-file.properties

# 查看建立的configmap:
# kubectl get configmap game-env -o yaml
apiVersion: v1
data:
  allowed: '"true"'
  enemies: aliens
  lives: "3"
kind: ConfigMap
metadata:
  creationTimestamp: 2018-06-15T10:17:59Z
  name: game-env
  namespace: default
  resourceVersion: "153612"
  selfLink: /api/v1/namespaces/default/configmaps/game-env
  uid: 60bb2081-7085-11e8-96f7-000c295f81fb
在指定文件的時候指定KEY

使用指定文件的方式定義ConfigMap默認狀況是使用的文件名爲KEY,其實咱們也能夠自定義key值:

kubectl create configmap game-3 --from-file=<my-key-name>=<path-to-file>

三、定義Pod使用ConfigMap
Pod中加載ConfigMap常見的有兩種方式:

  • 在Pod中定義環境變量參數,引用ConfigMap
  • 經過volume mount使用ConfigMap
Pod中指定引用ConfigMap定義環境變量參數

若是ConfigMap有以下定義:

# cat config-map.yaml 

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-test
data: 
  apploglevel: info
  appdatadir: /var/data

在pod中引用此configmap:

# cat configmap-pod.yaml

   apiVersion: v1
   kind: Pod
   metadata:
     name: configmap-pod
   spec:
     containers:
       - name: test-container
         image: busybox
         command: [ "/bin/sh", "-c", "env|grep TEST" ]   # 獲取只包含TEST開頭的環境變量名稱
         env:
           # Define the environment variable
           - name: TEST-KEY1                             # 容器中的環境變量參數
             valueFrom:                                  
               configMapKeyRef:                          # 參數來源於configmap
                 # The ConfigMap containing the value you want to assign to TEST-KEY1
                 name: config-test                       # 指定已經存在的configmap的名稱
                 key: apploglevel                        # 指定此configmap中須要引用的key
           - name: TEST-KEY2
             valueFrom:
               configMapKeyRef:
                 # The ConfigMap containing the value you want to assign to TEST-KEY2
                 name: config-test                       # 這裏能夠指定不一樣configmap
                 key: appdatadir
     restartPolicy: Never                                # 執行完啓動命令後將退出,再也不被系統自動重啓

建立configmap和定義的POD:

kubectl create -f config-map.yaml
kubectl create -f configmap-pod.yaml

查看pod,執行完命令以後已經正常退出:

# kubectl get pod -o wide
NAME            READY     STATUS      RESTARTS   AGE       IP         NODE
configmap-pod   0/1       Completed   0          57s       10.2.6.3   10.0.0.3

查看輸出的環境變量:

# kubectl logs configmap-pod

TEST-KEY1=info
TEST-KEY2=/var/data
Pod中引用指定configmap的全部參數

當咱們須要引用configmap中的定義的全部參數和變量時,可使用envFrom 參數來指定configMap:

# cat pod-configmap1.yaml 
   apiVersion: v1
   kind: Pod
   metadata:
     name: test-pod
   spec:
     containers:
       - name: test-container
         image: busybox
         command: [ "/bin/sh", "-c", "env" ]
         envFrom:                             
         - configMapRef:                       # 此處再也不指定key
             name: config-test                 # 指定configmap
     restartPolicy: Never

運行pod,能夠發現和configmap中定義的參數一致:

# kubectl logs test-pod |grep app

apploglevel=info
appdatadir=/var/data
經過VolumeMount使用configmap

咱們也能夠在定義pod時,將configmap以卷的形式掛載到容器中的目錄,這樣就至關於容器直接使用這個配置文件了:

apiVersion: v1
kind: Pod
metadata:
  name: volume-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "ls -l /etc/config/" ]
      volumeMounts: 
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap: 
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: config-test 
  restartPolicy: Never

這樣就將對應的參數掛載到了容器中的/etc/config目錄,登陸容器,能夠看到:

# ls -l /etc/config/
total 0
lrwxrwxrwx    1 root     root            17 Jun 17 09:07 appdatadir -> ..data/appdatadir
lrwxrwxrwx    1 root     root            18 Jun 17 09:07 apploglevel -> ..data/apploglevel

對應的文件中記錄了參數值,/etc/config 路徑下若是有其餘文件,使用這種方式會清除此路徑下以前的全部文件。

在實際的應用中,通常是經過configmap指定文件,掛載的configmap卷中會有一個以key值命名的文件,文件中包含了參數信息:

# kubectl  get configmap game-config -o yaml
apiVersion: v1
data:
  game.properties: |-
    enemies=aliens
    lives=3
    enemies.cheat=true
    enemies.cheat.level=noGoodRotten
    secret.code.passphrase=UUDDLRLRBABAS
    secret.code.allowed=true
    secret.code.lives=30
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
    how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
  creationTimestamp: 2018-06-15T09:29:39Z
  name: game-config
  namespace: default
  resourceVersion: "150723"
  selfLink: /api/v1/namespaces/default/configmaps/game-config
  uid: a079ab6c-707e-11e8-96f7-000c295f81fb

建立使用volume掛載此configmap的pod:

apiVersion: v1
kind: Pod
metadata:
  name: volume-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "sleep 150" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: game-config
  restartPolicy: Never

登陸此容器,能夠看到對應的兩個文件game.propertiesui.properties,裏面的參數都是以鍵值存儲:

# kubectl exec -it volume-test-pod sh
/ # ls -l /etc/config/
total 0
lrwxrwxrwx    1 root     root            22 Jun 17 09:22 game.properties -> ..data/game.properties
lrwxrwxrwx    1 root     root            20 Jun 17 09:22 ui.properties -> ..data/ui.properties

/etc/config # cat game.properties 
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30/etc/config # 

/etc/config # cat ui.properties 
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

固然,這裏咱們也能夠定義掛載的文件名稱和路徑,使用path指定,對上面的例子進行修改:

apiVersion: v1
kind: Pod
metadata:
  name: volume-test-pod
spec:
  containers:
    - name: test-container
      image: busybox
      command: [ "/bin/sh", "-c", "sleep 150" ]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
        name: game-config
        items:
        - key: ui.properties         # 這裏的KEY爲confmap中的data 的key 
          path: ui/keys              # 文件路徑,這裏表示參數文件爲 /etc/config/ui/keys
  restartPolicy: Never

登陸pod後,查看內容以下:

/etc/config # ls
ui
/etc/config # cat ui/keys 
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

使用volume的方式指定路徑後,此路徑的下以前的文件都會被清除,只能顯示指定的item文件

使用ConfigMap的限制條件:

  • ConMap必須在Pod以前建立,不然將沒法建立須要引用configMap的Pod,除非Pod中指定此ConfigMap爲可選。
  • ConMap受Namespace限制,只有處於相同namespace中的Pod才能夠引用它。
  • kebulete只支持能夠被API Server管理的Pod使用ConfigMap。kubelet在本地Node上經過Kubelet REST API,--manifest-url或--config自動建立的靜態Pod將沒法引用ConfigMap。
  • 在Pod對configMap進行掛載時,掛載的目錄下若是原來還有其餘文件,則容器內的該目錄將會被掛載的ConfigMap覆蓋。若是應用程序要保留原來的其餘文件,須要進行特殊處理。
  • 特殊處理思路:能夠將ConfigMap掛載到容器的臨時目錄,再經過啓動腳本將配置文件複製到或者連接到應用所用的實際配置目錄下。
相關文章
相關標籤/搜索