1. 程式人生 > >Pod Preset玩轉K8S容器時區自動配置

Pod Preset玩轉K8S容器時區自動配置

摘要: 通過Pod Preset自動配置容器的時區

緣由

預設的情況,在K8S裡啟動一個容器,該容器的設定的時區是UTC0,但是對於很多客戶而言,其主機環境並不在UTC0。例如中國客戶在UTC8。如果不把容器的時區和主機主機設定為一致,則在查詢日誌等時候將非常不方便,也容易造成誤解。但是K8S以及Docker容器沒有一個簡便的設定/開關在系統層面做配置。都需要我們從單個容器入手做設定,具體方法如下:

純Docker的時區設定方式

Docker引擎提供了兩種設定方式,分別是通過環境變數以及掛載主機檔案方式來完成

方式一:設定容器的時區環境變數

先看看沒有設定前,容器的情況:

docker run -it --rm centos
date
cat /etc/localtime

從輸出可以看出,容器和主機差了8個時區

我們通過環境變數的方式來改變容器的時區:

docker run -it --rm -e "TZ=Asia/Shanghai" centos
date
cat /etc/localtime

從輸出可以看出,雖然沒有改變對應的localtime檔案,但是容器和主機的時區是一致的了。

方式二:掛載主機的時區檔案到容器中

docker run -it --rm -v /etc/localtime:/etc/localtime  centos
date
cat /etc/localtime

從輸出可以看出,容器和主機的時區是一致的了,而且使用了本機的時區檔案。

Kubernetes的時區設定方式

在K8S中,可以參考Docker的方式進行設定

通過環境變數設定

apiVersion: v1
kind: Pod
metadata:
  name: pod-env-tz
spec:
  containers:
  - name: ngx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    env:
      - name: TZ
        value: Asia/Shanghai

通過掛載主機時區檔案設定

apiVersion: v1
kind: Pod
metadata:
  name: pod-vol-tz
spec:
  containers:
  - name: ngx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: tz-config
      mountPath: /etc/localtime
      readOnly: true
  volumes:
  - name: tz-config
    hostPath:
      path: /etc/localtime

這裡引出了一個問題,難道每次每個容器都要做這樣的配置才可以麼?可否在系統層面設定,而無需在對應yaml檔案體現呢?不然yaml檔案將過於囉嗦。答案是使用K8S的特性Pod Preset來控制容器啟動前先配置好對應時區環境變數,或者掛載主機檔案。下面我們通過配置環境變數的方式說明,掛載檔案是類似的,就不重複了。

通過Pod Preset預設定時區環境變數

啟用Pod Preset

Pod Preset目前還是alpha階段,預設是沒有啟用的,所以需要通過以下步驟啟用:

咱們以阿里雲的Kubernetes服務為例(如果還沒有,可以嘗試一下,一鍵就可以開通,還免費哦)。阿里雲的Kubernetes服務的master元件(API Server, Scheduler, Controller)都是通過Static Pod的方式用Kubelet啟動,所以需要更改對應的yaml來啟用Pod Preset:

編輯/etc/kubernetes/manifests/kube-apiserver.yaml,

  • -runtime-config增加settings.k8s.io/v1alpha1=true
  • --admission-control增加PodPreset`

儲存後kubelet會自動重啟kube-apiserver元件。我們需要同時更改3臺機器的master才可以。在期間你將收到類似以下的告警,在api server重啟成功後會自動恢復

驗證配置成功

  • 確保api server已經恢復,如果恢復將收到如下通知資訊:

  • kubectl可以查詢Pod Preset。在開關沒有開啟成功前,是無法呼叫以下命令的
kubectl get podpresets

配置設定時區的Pod Preset

對應的Pod Preset物件建立檔案如下:

apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-tz-env
spec:
  selector:
    matchLabels:
  env:
    - name: TZ
      value: Asia/Shanghai

這裡需要注意的地方是,一定需要寫selector...matchLabels,但是matchLabels為空,標示應用於所有容器,這個正式我們所期望的

kubectl apply -f allow-tz-env.yaml
kubectl get podpresets

可以得到建立成功的Pod Preset列表:

image

以普通的方式建立容器,但是環境變數被Pod Preset注入了

apiVersion: v1
kind: Pod
metadata:
  name: pod-no-tz
spec:
  containers:
  - name: ngx
    image: nginx:latest
    imagePullPolicy: IfNotPresent

進入容器看看對應的環境變數:

從輸出可以看出,容器已經被預設配置了時區的環境變數,對應的時區是Asia/Shanghai

小結

至此,我們就完成了容器的時區的"自動"配置了。Pod Preset的預設功能還是非常便利的,目前這塊還在演進中,但是已經能大大簡化了相關的管理工作,將這些配置從開發者手中解脫出來,變成系統管理配置。

需要注意的是,Pod Preset是namespace級別的物件,其作用範圍只能是同一個名稱空間下容器。

給社群的建議

建議Kubernetes社群可以在kubelet的啟動引數重,增加一個開關,用來設定容器的預設時區,畢竟這個是很常見的實踐

參考文件

原文連結