Kubernetes
  • 序言
  • 基礎入門
    • Kubernetes 簡介
    • Kubernetes 基本概念
    • Kubernetes 101
    • Kubernetes 201
    • Kubernetes 集群
  • 核心原理
    • 核心原理
    • 架構原理
    • 設計理念
    • 核心組件
      • etcd
      • kube-apiserver
      • kube-scheduler
      • kube-controller-manager
      • kubelet
      • kube-proxy
      • kube-dns
      • Federation
      • kubeadm
      • hyperkube
      • kubectl
    • 資源對象
      • Autoscaling
      • ConfigMap
      • CronJob
      • CustomResourceDefinition
      • DaemonSet
      • Deployment
      • Ingress
      • Job
      • LocalVolume
      • Namespace
      • NetworkPolicy
      • Node
      • PersistentVolume
      • Pod
      • PodPreset
      • ReplicaSet
      • Resource Quota
      • Secret
      • SecurityContext
      • Service
      • ServiceAccount
      • StatefulSet
      • Volume
  • 部署配置
    • 部署指南
    • kubectl 安裝
    • 單機部署
    • 特性開關
    • 最佳配置
    • 版本支持
    • 集群部署
      • kubeadm
      • kops
      • Kubespray
      • Azure
      • Windows
      • LinuxKit
      • kubeasz
    • 附加組件
      • Addon-manager
      • DNS
      • Dashboard
      • 監控
      • 日誌
      • Metrics
      • GPU
      • Cluster Autoscaler
      • ip-masq-agent
    • Kubernetes-The-Hard-Way
      • 準備部署環境
      • 安裝必要工具
      • 創建計算資源
      • 配置創建證書
      • 配置生成配置
      • 配置生成密鑰
      • 部署 Etcd 群集
      • 部署控制節點
      • 部署計算節點
      • 配置 Kubectl
      • 配置網絡路由
      • 部署 DNS 擴展
      • 煙霧測試
      • 刪除集群
  • 插件擴展
    • API 擴展
      • Aggregation
      • CustomResourceDefinition
    • 訪問控制
      • 認證
      • RBAC 授權
      • 准入控制
    • Scheduler 擴展
    • 網絡插件
      • CNI
      • Flannel
      • Calico
      • Weave
      • Cilium
      • OVN
      • Contiv
      • SR-IOV
      • Romana
      • OpenContrail
      • Kuryr
    • 運行時插件 CRI
      • CRI-tools
      • Frakti
    • 存儲插件
      • 容器存儲接口 CSI
      • FlexVolume
      • glusterfs
    • 網絡策略
    • Ingress Controller
      • Ingress + Letsencrypt
      • minikube Ingress
      • Traefik Ingress
      • Keepalived-VIP
    • Cloud Provider 擴展
    • Device 插件
  • 服務治理
    • 服務治理
      • 一般準則
      • 滾動升級
      • Helm
      • Operator
      • Service Mesh
      • Linkerd
      • Linkerd2
    • Istio
      • 安裝
      • 流量管理
      • 安全管理
      • 策略管理
      • 度量管理
      • 排錯
      • 社區
    • Devops
      • Draft
      • Jenkins X
      • Spinnaker
      • Kompose
      • Skaffold
      • Argo
      • Flux GitOps
  • 實踐案例
    • 實踐概覽
    • 資源控制
    • 集群高可用
    • 應用高可用
    • 調試
    • 端口映射
    • 端口轉發
    • 用戶管理
    • GPU
    • HugePage
    • 安全
    • 審計
    • 備份恢復
    • 證書輪換
    • 大規模集群
    • 大數據與機器學習
      • Spark
      • Tensorflow
    • Serverless
  • 排錯指南
    • 排錯概覽
    • 集群排錯
    • Pod 排錯
    • 網絡排錯
    • PV 排錯
      • AzureDisk
      • AzureFile
    • Windows 排錯
    • 雲平臺排錯
      • Azure
    • 排錯工具
  • 社區貢獻
    • 開發指南
    • 單元測試和集成測試
    • 社區貢獻
  • 附錄
    • 生態圈
    • 學習資源
    • 國內鏡像
    • 如何貢獻
    • 參考文檔
Powered by GitBook
On this page
  • API 版本對照表
  • Pod 定義
  • Docker 鏡像支持
  • Pod 生命週期
  • 使用 Volume
  • 私有鏡像
  • RestartPolicy
  • 環境變量
  • 鏡像拉取策略
  • 訪問 DNS 的策略
  • 使用主機的 IPC 命名空間
  • 使用主機的網絡命名空間
  • 使用主機的 PID 空間
  • 設置 Pod 的 hostname
  • 設置 Pod 的子域名
  • 設置 Pod 的 DNS 選項
  • 資源限制
  • 健康檢查
  • Init Container
  • 容器生命週期鉤子
  • 使用 Capabilities
  • 限制網絡帶寬
  • 調度到指定的 Node 上
  • 自定義 hosts
  • HugePages
  • 優先級
  • PodDisruptionBudget
  • Sysctls
  • Pod 時區
  • 參考文檔
  1. 核心原理
  2. 資源對象

Pod

PreviousPersistentVolumeNextPodPreset

Last updated 1 year ago

Pod 是一組緊密關聯的容器集合,它們共享 IPC 和 Network namespace,是 Kubernetes 調度的基本單位。Pod 的設計理念是支持多個容器在一個 Pod 中共享網絡和文件系統,可以通過進程間通信和文件共享這種簡單高效的方式組合完成服務。

Pod 的特徵

  • 包含多個共享 IPC 和 Network namespace 的容器,可直接通過 localhost 通信

  • 所有 Pod 內容器都可以訪問共享的 Volume,可以訪問共享數據

  • 無容錯性:直接創建的 Pod 一旦被調度後就跟 Node 綁定,即使 Node 掛掉也不會被重新調度(而是被自動刪除),因此推薦使用 Deployment、Daemonset 等控制器來容錯

  • 優雅終止:Pod 刪除的時候先給其內的進程發送 SIGTERM,等待一段時間(grace period)後才強制停止依然還在運行的進程

  • 特權容器(通過 SecurityContext 配置)具有改變系統配置的權限(在網絡插件中大量應用)

Kubernetes v1.8+ 支持容器間共享 PID namespace,需要 docker >= 1.13.1,並配置 kubelet --docker-disable-shared-pid=false。

在 Kubernetes v1.10+ --docker-disable-shared-pid 已被棄用,如果要共享 PID namespace,需要設置 v1.PodSpec 中的 ShareProcessNamespace 爲 true,如下所示

spec:
  shareProcessNamespace: true

API 版本對照表

Kubernetes 版本
Core API 版本
默認開啓

v1.5+

core/v1

是

Pod 定義

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80

在生產環境中,推薦使用 Deployment、StatefulSet、Job 或者 CronJob 等控制器來創建 Pod,而不推薦直接創建 Pod。

Docker 鏡像支持

Dockerfile 指令
描述
支持
說明

ENTRYPOINT

啓動命令

是

containerSpec.command

CMD

命令的參數列表

是

containerSpec.args

ENV

環境變量

是

containerSpec.env

EXPOSE

對外開放的端口

否

使用 containerSpec.ports.containerPort 替代

VOLUME

數據卷

是

使用 volumes 和 volumeMounts

USER

進程運行用戶以及用戶組

是

securityContext.runAsUser/supplementalGroups

WORKDIR

工作目錄

是

containerSpec.workingDir

STOPSIGNAL

停止容器時給進程發送的信號

是

SIGKILL

HEALTHCHECK

健康檢查

否

使用 livenessProbe 和 readinessProbe 替代

SHELL

運行啓動命令的 SHELL

否

使用鏡像默認 SHELL 啓動命令

Pod 生命週期

Kubernetes 以 PodStatus.Phase 抽象 Pod 的狀態(但並不直接反映所有容器的狀態)。可能的 Phase 包括

  • Pending: API Server已經創建該Pod,但一個或多個容器還沒有被創建,包括通過網絡下載鏡像的過程。

  • Running: Pod中的所有容器都已經被創建且已經調度到 Node 上面,但至少有一個容器還在運行或者正在啓動。

  • Succeeded: Pod 調度到 Node 上面後均成功運行結束,並且不會重啓。

  • Failed: Pod中的所有容器都被終止了,但至少有一個容器退出失敗(即退出碼不爲 0 或者被系統終止)。

  • Unknonwn: 狀態未知,因爲一些原因Pod無法被正常獲取,通常是由於 apiserver 無法與 kubelet 通信導致。

可以用 kubectl 命令查詢 Pod Phase:

$ kubectl get pod reviews-v1-5bdc544bbd-5qgxj -o jsonpath="{.status.phase}"
Running

PodSpec 中的 restartPolicy 可以用來設置是否對退出的 Pod 重啓,可選項包括 Always、OnFailure、以及 Never。比如

  • 單容器的 Pod,容器成功退出時,不同 restartPolicy 時的動作爲

    • Always: 重啓 Container; Pod phase 保持 Running.

    • OnFailure: Pod phase 變成 Succeeded.

    • Never: Pod phase 變成 Succeeded.

  • 單容器的 Pod,容器失敗退出時,不同 restartPolicy 時的動作爲

    • Always: 重啓 Container; Pod phase 保持 Running.

    • OnFailure: 重啓 Container; Pod phase 保持 Running.

    • Never: Pod phase 變成 Failed.

  • 2個容器的 Pod,其中一個容器在運行而另一個失敗退出時,不同 restartPolicy 時的動作爲

    • Always: 重啓 Container; Pod phase 保持 Running.

    • OnFailure: 重啓 Container; Pod phase 保持 Running.

    • Never: 不重啓 Container; Pod phase 保持 Running.

  • 2個容器的 Pod,其中一個容器停止而另一個失敗退出時,不同 restartPolicy 時的動作爲

    • Always: 重啓 Container; Pod phase 保持 Running.

    • OnFailure: 重啓 Container; Pod phase 保持 Running.

    • Never: Pod phase 變成 Failed.

  • 單容器的 Pod,容器內存不足(OOM),不同 restartPolicy 時的動作爲

    • Always: 重啓 Container; Pod phase 保持 Running.

    • OnFailure: 重啓 Container; Pod phase 保持 Running.

    • Never: 記錄失敗事件; Pod phase 變成 Failed.

  • Pod 還在運行,但磁盤不可訪問時

    • 終止所有容器

    • Pod phase 變成 Failed

    • 如果 Pod 是由某個控制器管理的,則重新創建一個 Pod 並調度到其他 Node 運行

  • Pod 還在運行,但由於網絡分區故障導致 Node 無法訪問

    • Node controller等待 Node 事件超時

    • Node controller 將 Pod phase 設置爲 Failed.

    • 如果 Pod 是由某個控制器管理的,則重新創建一個 Pod 並調度到其他 Node 運行

使用 Volume

Volume 可以爲容器提供持久化存儲,比如

apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}

私有鏡像

在使用私有鏡像時,需要創建一個 docker registry secret,並在容器中引用。

創建 docker registry secret:

kubectl create secret docker-registry regsecret --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

比如使用 Azure Container Registry(ACR):

ACR_NAME=dregistry
SERVICE_PRINCIPAL_NAME=acr-service-principal

# Populate the ACR login server and resource id.
ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --query loginServer --output tsv)
ACR_REGISTRY_ID=$(az acr show --name $ACR_NAME --query id --output tsv)

# Create a contributor role assignment with a scope of the ACR resource.
SP_PASSWD=$(az ad sp create-for-rbac --name $SERVICE_PRINCIPAL_NAME --role Reader --scopes $ACR_REGISTRY_ID --query password --output tsv)

# Get the service principle client id.
CLIENT_ID=$(az ad sp show --id http://$SERVICE_PRINCIPAL_NAME --query appId --output tsv)

# Create secret
kubectl create secret docker-registry acr-auth --docker-server $ACR_LOGIN_SERVER --docker-username $CLIENT_ID --docker-password $SP_PASSWD --docker-email local@local.domain

在引用 docker registry secret 時,有兩種可選的方法:

第一種是直接在 Pod 描述文件中引用該 secret:

apiVersion: v1
kind: Pod
metadata:
  name: private-reg
spec:
  containers:
    - name: private-reg-container
      image: dregistry.azurecr.io/acr-auth-example
  imagePullSecrets:
    - name: acr-auth

第二種是把 secret 添加到 service account 中,再通過 service account 引用(一般是某個 namespace 的 default service account):

$ kubectl get secrets myregistrykey
$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
$ kubectl get serviceaccounts default -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2015-08-07T22:02:39Z
  name: default
  namespace: default
  selfLink: /api/v1/namespaces/default/serviceaccounts/default
  uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey

RestartPolicy

支持三種 RestartPolicy

  • Always:當容器失效時,由Kubelet自動重啓該容器。RestartPolicy的默認值。

  • OnFailure:當容器終止運行且退出碼不爲0時由Kubelet重啓。

  • Never:無論何種情況下,Kubelet都不會重啓該容器。

注意,這裏的重啓是指在 Pod 所在 Node 上面本地重啓,並不會調度到其他 Node 上去。

環境變量

環境變量爲容器提供了一些重要的資源,包括容器和 Pod 的基本信息以及集群中服務的信息等:

(1) hostname

HOSTNAME 環境變量保存了該 Pod 的 hostname。

(2)容器和 Pod 的基本信息

apiVersion: v1
kind: Pod
metadata:
  name: test
spec:
  containers:
    - name: test-container
      image: gcr.io/google_containers/busybox
      command: ["sh", "-c"]
      args:
      - env
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: MY_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: MY_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never

(3) 集群中服務的信息

容器的環境變量中還可以引用容器運行前創建的所有服務的信息,比如默認的 kubernetes 服務對應以下環境變量:

KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.0.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443

鏡像拉取策略

支持三種 ImagePullPolicy

  • Always:不管本地鏡像是否存在都會去倉庫進行一次鏡像拉取。校驗如果鏡像有變化則會覆蓋本地鏡像,否則不會覆蓋。

  • Never:只是用本地鏡像,不會去倉庫拉取鏡像,如果本地鏡像不存在則Pod運行失敗。

  • IfNotPresent:只有本地鏡像不存在時,纔會去倉庫拉取鏡像。ImagePullPolicy的默認值。

注意:

  • 默認爲 IfNotPresent,但 :latest 標籤的鏡像默認爲 Always。

  • 拉取鏡像時 docker 會進行校驗,如果鏡像中的 MD5 碼沒有變,則不會拉取鏡像數據。

  • 生產環境中應該儘量避免使用 :latest 標籤,而開發環境中可以藉助 :latest 標籤自動拉取最新的鏡像。

訪問 DNS 的策略

通過設置 dnsPolicy 參數,設置 Pod 中容器訪問 DNS 的策略

  • ClusterFirst:優先基於 cluster domain (如 default.svc.cluster.local) 後綴,通過 kube-dns 查詢 (默認策略)

  • Default:優先從 Node 中配置的 DNS 查詢

使用主機的 IPC 命名空間

通過設置 spec.hostIPC 參數爲 true,使用主機的 IPC 命名空間,默認爲 false。

使用主機的網絡命名空間

通過設置 spec.hostNetwork 參數爲 true,使用主機的網絡命名空間,默認爲 false。

使用主機的 PID 空間

通過設置 spec.hostPID 參數爲 true,使用主機的 PID 命名空間,默認爲 false。

apiVersion: v1
kind: Pod
metadata:
  name: busybox1
  labels:
    name: busybox
spec:
  hostIPC: true
  hostPID: true
  hostNetwork: true
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    name: busybox

設置 Pod 的 hostname

通過 spec.hostname 參數實現,如果未設置默認使用 metadata.name 參數的值作爲 Pod 的 hostname。

設置 Pod 的子域名

通過 spec.subdomain 參數設置 Pod 的子域名,默認爲空。

比如,指定 hostname 爲 busybox-2 和 subdomain 爲 default-subdomain,完整域名爲 busybox-2.default-subdomain.default.svc.cluster.local,也可以簡寫爲 busybox-2.default-subdomain.default:

apiVersion: v1
kind: Pod
metadata:
  name: busybox2
  labels:
    name: busybox
spec:
  hostname: busybox-2
  subdomain: default-subdomain
  containers:
  - image: busybox
    command:
      - sleep
      - "3600"
    name: busybox

注意:

  • 默認情況下,DNS 爲 Pod 生成的 A 記錄格式爲 pod-ip-address.my-namespace.pod.cluster.local,如 1-2-3-4.default.pod.cluster.local

  • 上面的示例還需要在 default namespace 中創建一個名爲 default-subdomain(即 subdomain)的 headless service,否則其他 Pod 無法通過完整域名訪問到該 Pod(只能自己訪問到自己)

kind: Service
apiVersion: v1
metadata:
  name: default-subdomain
spec:
  clusterIP: None
  selector:
    name: busybox
  ports:
  - name: foo # Actually, no port is needed.
    port: 1234
    targetPort: 1234

注意,必須爲 headless service 設置至少一個服務端口(spec.ports,即便它看起來並不需要),否則 Pod 與 Pod 之間依然無法通過完整域名來訪問。

設置 Pod 的 DNS 選項

從 v1.9 開始,可以在 kubelet 和 kube-apiserver 中設置 --feature-gates=CustomPodDNS=true 開啓設置每個 Pod DNS 地址的功能。

注意該功能在 v1.10 中爲 Beta 版,v1.9 中爲 Alpha 版。

apiVersion: v1
kind: Pod
metadata:
  namespace: default
  name: dns-example
spec:
  containers:
    - name: test
      image: nginx
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 1.2.3.4
    searches:
      - ns1.svc.cluster.local
      - my.dns.search.suffix
    options:
      - name: ndots
        value: "2"
      - name: edns0

對於舊版本的集群,可以使用 ConfigMap 來自定義 Pod 的 /etc/resolv.conf,如

kind: ConfigMap
apiVersion: v1
metadata:
  name: resolvconf
  namespace: default
data:
  resolv.conf: |
    search default.svc.cluster.local svc.cluster.local cluster.local
    nameserver 10.0.0.10

---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: dns-test
  namespace: default
spec:
  replicas: 1
  template:
    metadata:
      labels:
        name: dns-test
    spec:
      containers:
        - name: dns-test
          image: alpine
          stdin: true
          tty: true
          command: ["sh"]
          volumeMounts:
            - name: resolv-conf
              mountPath: /etc/resolv.conf
              subPath: resolv.conf
      volumes:
        - name: resolv-conf
          configMap:
            name: resolvconf
            items:
            - key: resolv.conf
              path: resolv.conf

資源限制

Kubernetes 通過 cgroups 限制容器的 CPU 和內存等計算資源,包括 requests(請求,調度器保證調度到資源充足的 Node 上,如果無法滿足會調度失敗)和 limits(上限)等:

  • spec.containers[].resources.limits.cpu:CPU 上限,可以短暫超過,容器也不會被停止

  • spec.containers[].resources.limits.memory:內存上限,不可以超過;如果超過,容器可能會被終止或調度到其他資源充足的機器上

  • spec.containers[].resources.limits.ephemeral-storage:臨時存儲(容器可寫層、日誌以及 EmptyDir 等)的上限,超過後 Pod 會被驅逐

  • spec.containers[].resources.requests.cpu:CPU 請求,也是調度 CPU 資源的依據,可以超過

  • spec.containers[].resources.requests.memory:內存請求,也是調度內存資源的依據,可以超過;但如果超過,容器可能會在 Node 內存不足時清理

  • spec.containers[].resources.requests.ephemeral-storage:臨時存儲(容器可寫層、日誌以及 EmptyDir 等)的請求,調度容器存儲的依據

比如 nginx 容器請求 30% 的 CPU 和 56MB 的內存,但限制最多隻用 50% 的 CPU 和 128MB 的內存:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
  containers:
    - image: nginx
      name: nginx
      resources:
        requests:
          cpu: "300m"
          memory: "56Mi"
        limits:
          cpu: "500m"
          memory: "128Mi"

注意

  • CPU 的單位是 CPU 個數,可以用 millicpu (m) 表示少於 1 個 CPU 的情況,如 500m = 500millicpu = 0.5cpu,而一個 CPU 相當於

    • AWS 上的一個 vCPU

    • GCP 上的一個 Core

    • Azure 上的一個 vCore

    • 物理機上開啓超線程時的一個超線程

  • 內存的單位則包括 E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki 等。

  • 從 v1.10 開始,可以設置 kubelet ----cpu-manager-policy=static 爲 Guaranteed(即 requests.cpu 與 limits.cpu 相等)Pod 綁定 CPU(通過 cpuset cgroups)。

健康檢查

爲了確保容器在部署後確實處在正常運行狀態,Kubernetes 提供了兩種探針(Probe)來探測容器的狀態:

  • LivenessProbe:探測應用是否處於健康狀態,如果不健康則刪除並重新創建容器。

  • ReadinessProbe:探測應用是否啓動完成並且處於正常服務狀態,如果不正常則不會接收來自 Kubernetes Service 的流量,即將該Pod從Service的endpoint中移除。

Kubernetes 支持三種方式來執行探針:

  • tcpSocket:對指定的容器 IP 及端口執行一個 TCP 檢查,如果端口是開放的則表示探測成功,否則表示失敗

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: nginx
  name: nginx
spec:
    containers:
    - image: nginx
      imagePullPolicy: Always
      name: http
      livenessProbe:
        httpGet:
          path: /
          port: 80
          httpHeaders:
          - name: X-Custom-Header
            value: Awesome
        initialDelaySeconds: 15
        timeoutSeconds: 1
      readinessProbe:
        exec:
          command:
          - cat
          - /usr/share/nginx/html/index.html
        initialDelaySeconds: 5
        timeoutSeconds: 1
    - name: goproxy
      image: gcr.io/google_containers/goproxy:0.1
      ports:
      - containerPort: 8080
      readinessProbe:
        tcpSocket:
          port: 8080
        initialDelaySeconds: 5
        periodSeconds: 10
      livenessProbe:
        tcpSocket:
          port: 8080
        initialDelaySeconds: 15
        periodSeconds: 20

Init Container

Pod 能夠具有多個容器,應用運行在容器裏面,但是它也可能有一個或多個先於應用容器啓動的 Init 容器。Init 容器在所有容器運行之前執行(run-to-completion),常用來初始化配置。

如果爲一個 Pod 指定了多個 Init 容器,那些容器會按順序一次運行一個。 每個 Init 容器必須運行成功,下一個才能夠運行。 當所有的 Init 容器運行完成時,Kubernetes 初始化 Pod 並像平常一樣運行應用容器。

下面是一個 Init 容器的示例:

apiVersion: v1
kind: Pod
metadata:
  name: init-demo
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  # These containers are run during pod initialization
  initContainers:
  - name: install
    image: busybox
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - http://kubernetes.io
    volumeMounts:
    - name: workdir
      mountPath: "/work-dir"
  dnsPolicy: Default
  volumes:
  - name: workdir
    emptyDir: {}

因爲 Init 容器具有與應用容器分離的單獨鏡像,使用 init 容器啓動相關代碼具有如下優勢:

  • 它們可以包含並運行實用工具,出於安全考慮,是不建議在應用容器鏡像中包含這些實用工具的。

  • 它們可以包含使用工具和定製化代碼來安裝,但是不能出現在應用鏡像中。例如,創建鏡像沒必要 FROM 另一個鏡像,只需要在安裝過程中使用類似 sed、 awk、 python 或 dig 這樣的工具。

  • 應用鏡像可以分離出創建和部署的角色,而沒有必要聯合它們構建一個單獨的鏡像。

  • 它們使用 Linux Namespace,所以對應用容器具有不同的文件系統視圖。因此,它們能夠具有訪問 Secret 的權限,而應用容器不能夠訪問。

  • 它們在應用容器啓動之前運行完成,然而應用容器並行運行,所以 Init 容器提供了一種簡單的方式來阻塞或延遲應用容器的啓動,直到滿足了一組先決條件。

Init 容器的資源計算,選擇一下兩者的較大值:

  • 所有 Init 容器中的資源使用的最大值

  • Pod 中所有容器資源使用的總和

Init 容器的重啓策略:

  • 如果 Init 容器執行失敗,Pod 設置的 restartPolicy 爲 Never,則 pod 將處於 fail 狀態。否則 Pod 將一直重新執行每一個 Init 容器直到所有的 Init 容器都成功。

  • 如果 Pod 異常退出,重新拉取 Pod 後,Init 容器也會被重新執行。所以在 Init 容器中執行的任務,需要保證是冪等的。

容器生命週期鉤子

容器生命週期鉤子(Container Lifecycle Hooks)監聽容器生命週期的特定事件,並在事件發生時執行已註冊的回調函數。支持兩種鉤子:

  • postStart: 容器創建後立即執行,注意由於是異步執行,它無法保證一定在 ENTRYPOINT 之前運行。如果失敗,容器會被殺死,並根據 RestartPolicy 決定是否重啓

  • preStop:容器終止前執行,常用於資源清理。如果失敗,容器同樣也會被殺死

而鉤子的回調函數支持兩種方式:

  • exec:在容器內執行命令,如果命令的退出狀態碼是 0 表示執行成功,否則表示失敗

  • httpGet:向指定 URL 發起 GET 請求,如果返回的 HTTP 狀態碼在 [200, 400) 之間表示請求成功,否則表示失敗

postStart 和 preStop 鉤子示例:

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    lifecycle:
      postStart:
        httpGet:
          path: /
          port: 80
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

使用 Capabilities

默認情況下,容器都是以非特權容器的方式運行。比如,不能在容器中創建虛擬網卡、配置虛擬網絡。

apiVersion: v1
kind: Pod
metadata:
  name: cap-pod
spec:
  containers:
  - name: friendly-container
    image: "alpine:3.4"
    command: ["/bin/sleep", "3600"]
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
        drop:
        - KILL

限制網絡帶寬

可以通過給 Pod 增加 kubernetes.io/ingress-bandwidth 和 kubernetes.io/egress-bandwidth 這兩個 annotation 來限制 Pod 的網絡帶寬

apiVersion: v1
kind: Pod
metadata:
  name: qos
  annotations:
    kubernetes.io/ingress-bandwidth: 3M
    kubernetes.io/egress-bandwidth: 4M
spec:
  containers:
  - name: iperf3
    image: networkstatic/iperf3
    command:
    - iperf3
    - -s

僅 kubenet 支持限制帶寬

目前只有 kubenet 網絡插件支持限制網絡帶寬,其他 CNI 網絡插件暫不支持這個功能。

kubenet 的網絡帶寬限制其實是通過 tc 來實現的

# setup qdisc (only once)
tc qdisc add dev cbr0 root handle 1: htb default 30
# download rate
tc class add dev cbr0 parent 1: classid 1:2 htb rate 3Mbit
tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip dst 10.1.0.3/32 flowid 1:2
# upload rate
tc class add dev cbr0 parent 1: classid 1:3 htb rate 4Mbit
tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip src 10.1.0.3/32 flowid 1:3

調度到指定的 Node 上

可以通過 nodeSelector、nodeAffinity、podAffinity 以及 Taints 和 tolerations 等來將 Pod 調度到需要的 Node 上。

也可以通過設置 nodeName 參數,將 Pod 調度到指定 node 節點上。

比如,使用 nodeSelector,首先給 Node 加上標籤:

kubectl label nodes <your-node-name> disktype=ssd

接着,指定該 Pod 只想運行在帶有 disktype=ssd 標籤的 Node 上:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

自定義 hosts

默認情況下,容器的 /etc/hosts 是 kubelet 自動生成的,並且僅包含 localhost 和 podName 等。不建議在容器內直接修改 /etc/hosts 文件,因爲在 Pod 啓動或重啓時會被覆蓋。

默認的 /etc/hosts 文件格式如下,其中 nginx-4217019353-fb2c5 是 podName:

$ kubectl exec nginx-4217019353-fb2c5 -- cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
fe00::0    ip6-mcastprefix
fe00::1    ip6-allnodes
fe00::2    ip6-allrouters
10.244.1.4    nginx-4217019353-fb2c5

從 v1.7 開始,可以通過 pod.Spec.HostAliases 來增加 hosts 內容,如

apiVersion: v1
kind: Pod
metadata:
  name: hostaliases-pod
spec:
  hostAliases:
  - ip: "127.0.0.1"
    hostnames:
    - "foo.local"
    - "bar.local"
  - ip: "10.1.2.3"
    hostnames:
    - "foo.remote"
    - "bar.remote"
  containers:
  - name: cat-hosts
    image: busybox
    command:
    - cat
    args:
    - "/etc/hosts"
$ kubectl logs hostaliases-pod
# Kubernetes-managed hosts file.
127.0.0.1    localhost
::1    localhost ip6-localhost ip6-loopback
fe00::0    ip6-localnet
fe00::0    ip6-mcastprefix
fe00::1    ip6-allnodes
fe00::2    ip6-allrouters
10.244.1.5    hostaliases-pod
127.0.0.1    foo.local
127.0.0.1    bar.local
10.1.2.3    foo.remote
10.1.2.3    bar.remote

HugePages

v1.8 + 支持給容器分配 HugePages,資源格式爲 hugepages-<size>(如 hugepages-2Mi)。使用前要配置

  • 開啓 --feature-gates="HugePages=true"

  • 在所有 Node 上面預分配好 HugePage ,以便 Kubelet 統計所在 Node 的 HugePage 容量

使用示例

apiVersion: v1
kind: Pod
metadata:
  generateName: hugepages-volume-
spec:
  containers:
  - image: fedora:latest
    command:
    - sleep
    - inf
    name: example
    volumeMounts:
    - mountPath: /hugepages
      name: hugepage
    resources:
      limits:
        hugepages-2Mi: 100Mi
  volumes:
  - name: hugepage
    emptyDir:
      medium: HugePages

注意事項

  • HugePage 資源的請求和限制必須相同

  • HugePage 以 Pod 級別隔離,未來可能會支持容器級的隔離

  • 基於 HugePage 的 EmptyDir 存儲卷最多隻能使用請求的 HugePage 內存

  • 使用 shmget() 的 SHM_HUGETLB 選項時,應用必須運行在匹配 proc/sys/vm/hugetlb_shm_group 的用戶組(supplemental group)中

優先級

從 v1.8 開始,可以爲 Pod 設置一個優先級,保證高優先級的 Pod 優先調度。

優先級調度功能目前爲 Beta 版,在 v1.11 版本中默認開啓。對 v1.8-1.10 版本中使用前需要開啓:

  • --feature-gates=PodPriority=true

  • --runtime-config=scheduling.k8s.io/v1alpha1=true --admission-control=Controller-Foo,Controller-Bar,...,Priority

爲 Pod 設置優先級前,先創建一個 PriorityClass,並設置優先級(數值越大優先級越高):

apiVersion: scheduling.k8s.io/v1alpha1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for XYZ service pods only."

Kubernetes 自動創建了 system-cluster-critical 和 system-node-critical 等兩個 PriorityClass,用於 Kubernetes 核心組件。

爲 Pod 指定優先級

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  priorityClassName: high-priority

當調度隊列有多個 Pod 需要調度時,優先調度高優先級的 Pod。而當高優先級的 Pod 無法調度時,Kubernetes 會嘗試先刪除低優先級的 Pod 再將其調度到對應 Node 上(Preemption)。

注意:受限於 Kubernetes 的調度策略,搶佔並不總是成功。

PodDisruptionBudget

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: zk-pdb
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: zookeeper

Sysctls

Sysctls 允許容器設置內核參數,分爲安全 Sysctls 和非安全 Sysctls:

  • 安全 Sysctls:即設置後不影響其他 Pod 的內核選項,只作用在容器 namespace 中,默認開啓。包括以下幾種

    • kernel.shm_rmid_forced

    • net.ipv4.ip_local_port_range

    • net.ipv4.tcp_syncookies

  • 非安全 Sysctls:即設置好有可能影響其他 Pod 和 Node 上其他服務的內核選項,默認禁止。如果使用,需要管理員在配置 kubelet 時開啓,如 kubelet --experimental-allowed-unsafe-sysctls 'kernel.msg*,net.ipv4.route.min_pmtu'

v1.6-v1.10 示例:

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
  annotations:
    security.alpha.kubernetes.io/sysctls: kernel.shm_rmid_forced=1
    security.alpha.kubernetes.io/unsafe-sysctls: net.ipv4.route.min_pmtu=1000,kernel.msgmax=1 2 3
spec:
  ...

從 v1.11 開始,Sysctls 升級爲 Beta 版本,不再區分安全和非安全 sysctl,統一通過 podSpec.securityContext.sysctls 設置,如

apiVersion: v1
kind: Pod
metadata:
  name: sysctl-example
spec:
  securityContext:
    sysctls:
    - name: kernel.shm_rmid_forced
      value: "0"
    - name: net.ipv4.route.min_pmtu
      value: "552"
    - name: kernel.msgmax
      value: "65536"
  ...

Pod 時區

很多容器都是配置了 UTC 時區,與國內集群的 Node 所在時區有可能不一致,可以通過 HostPath 存儲插件給容器配置與 Node 一樣的時區:

apiVersion: v1
kind: Pod
metadata:
  name: sh
  namespace: default
spec:
  containers:
  - image: alpine
    stdin: true
    tty: true
    volumeMounts:
    - mountPath: /etc/localtime
      name: time
      readOnly: true
  volumes:
  - hostPath:
      path: /etc/localtime
      type: ""
    name: time

參考文檔

通過 和其內容器的運行環境以及期望狀態,比如一個最簡單的 nginx pod 可以定義爲

目前,Kubernetes 僅支持使用 Docker 鏡像來創建容器,但並非支持 定義的所有行爲。如下表所示

更多掛載存儲卷的方法參考 。

Pod 的名字、命名空間、IP 以及容器的計算資源限制等可以以 的方式獲取並存儲到環境變量中。

由於環境變量存在創建順序的侷限性(環境變量中不包含後來創建的服務),推薦使用 來解析服務。

exec:在容器中執行一個命令,如果 返回 0 則表示探測成功,否則表示失敗

httpGet:對指定的容器 IP、端口及路徑執行一個 HTTP Get 請求,如果返回的 在 [200,400) 之間則表示探測成功,否則表示失敗

Kubernetes 提供了修改 的機制,可以按需要給容器增加或刪除。比如下面的配置給容器增加了 CAP_NET_ADMIN 並刪除了 CAP_KILL。

nodeAffinity、podAffinity 以及 Taints 和 tolerations 等的使用方法請參考 。

用來保證一組 Pod 同時運行的數量,這些 Pod 需要使用 Deployment、ReplicationController、ReplicaSet 或者 StatefulSet 管理。

yaml 或 json 描述 Pod
Dockerfile
Volume
Downward API
DNS
命令退出碼
狀態碼
Capabilities
調度器章節
PodDisruptionBudget (PDB)
What is Pod?
Kubernetes Pod Lifecycle
DNS Pods and Services
Container capabilities
Configure Liveness and Readiness Probes
Init Containers
Linux Capabilities
Manage HugePages
Document supported docker image (Dockerfile) features
pod