這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Kubernetes叢集搭建起來後,一直跑得很穩定。之前的關注點更多集中在安裝、配置、組件調試方面,一些細枝末節被忽略了。Pod中時區的設定就是其中之一。今天騰出功夫打算解決一下這個問題。
一、問題現象
在我的Kubernetes 1.3.7叢集的Master Node上,我們執行:
# dateMon Feb 20 11:49:20 CST 2017
之後,在該Node上隨意找到一個Pod中的Container,通過docker exec切入到容器內執行:
# docker exec -it 1975d68de07a /bin/bashroot@1975d68de07a:/# dateMon Feb 20 03:49:53 UTC 2017
我們發現Docker內輸出的當前date與Host上輸出的date是不一致的。這對於K8s叢集自身的運轉似乎並沒有多大影響,至少運行這麼長時間以來,未出現因為時間設定與Host不同而導致的問題。但是對跑在Pod中應用來說,這個時間設定的問題可能會給業務的運行帶來很多煩惱。
總之,一般來說,讓Pod裡的時間設定與Host上的Local time設定保持一致總是沒錯的。這裡我們就來嘗試解決這個問題。
二、Pod使用Host時區設定的方案
我有兩個K8s叢集環境,一個是基於ubuntu 14.04 node的k8s 1.3.7 環境,一個是基於ubuntu 16.04 node以kubeadm安裝的k8s 1.5.1環境。由於ubuntu 14.04和ubuntu 16.04 Host在timezone的設定上略有差異,因此我們也要分為幾種情況對應(redhat系的os這裡暫不涉及,但原理是相同的):
0、ubuntu上時區設定
在Ubuntu上,/etc/localtime是系統的本地時區設定檔案,直接影響到系統的當前date輸出。不過在Ubuntu 14.04和Ubuntu 16.04上,這個檔案的內容稍有不同:
在Ubuntu 14.04上,/etc/localtime就是一個regular file,其儲存著本地時區的配置資料:
# file /etc/localtime/etc/localtime: timezone data, version 2, 2 gmt time flags, 2 std time flags, no leap seconds, 16 transition times, 2 abbreviation chars
在我的Node上,其內容與/usr/share/zoneinfo/Asia/Shanghai指向的內容一致,好像/etc/localtime是這麼得來的:
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
而在Ubuntu 16.04上,/etc/localtime是一個symbolic link,連結到檔案:/usr/share/zoneinfo/Asia/Shanghai
# file /etc/localtime/etc/localtime: symbolic link to /usr/share/zoneinfo/Asia/Shanghai
/usr/share/zoneinfo下儲存著真正的時區設定檔案,/usr/share/zoneinfo/Asia/Shanghai也是一個符號連結,指向的是/usr/share/zoneinfo/PRC:
# file /usr/share/zoneinfo/PRC/usr/share/zoneinfo/PRC: timezone data, version 2, 2 gmt time flags, 2 std time flags, no leap seconds, 16 transition times, 2 abbreviation chars
在14.04 Node上,/etc/localtime與/usr/share/zoneinfo/PRC檔案的內容是一模一樣的。但在14.04的Pod中,這兩個檔案內容卻是不同的:
# docker exec -it fe936562b6ee /bin/bash# diff /etc/localtime /usr/share/zoneinfo/PRCBinary files /etc/localtime and /usr/share/zoneinfo/PRC differ
因此,如果要讓Pod使用的本地時區設定與Host的一致,就必須在Pod的manifest中做些“手腳”,接下來我們來分門別類地仔細看看。
1、Host 14.04,Pod 16.04
我們在14.04的node上隨意run一個16.04的容器,可以看到:
# docker run -it ubuntu:16.04 /bin/bashroot@bf7cec08df23:/# ls -l /etc/localtimelrwxrwxrwx 1 root root 27 Jan 19 16:33 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
容器內的系統時間與host時間是不一致的。
我們來建立一個使用ubuntu 16.04的docker image:
//1604pod-image-dockerfileFROM ubuntu:16.04CMD ["tail", "-f", "/var/log/bootstrap.log"]
在本地構建這個image:
# docker build -f ./1604pod-image-dockerfile -t 1604podimage:latest .Sending build context to Docker daemon 5.632 kBStep 1 : FROM ubuntu:16.04 ---> f49eec89601eStep 2 : CMD tail -f /var/log/bootstrap.log ---> Using cache ---> 06ffb5c85d7cSuccessfully built 06ffb5c85d7c# docker images|grep 1604pod1604podimage latest 06ffb5c85d7c 28 minutes ago 129.5 MB
我們來編寫這個運行於16.04之上的pod的manifest檔案:
//1604-pod-on-1404-host.yamlapiVersion: extensions/v1beta1kind: Deploymentmetadata: name: my-testpodspec: replicas: 1 template: metadata: labels: run: my-testpod spec: containers: - name: my-testpod image: 1604podimage:latest imagePullPolicy: IfNotPresent volumeMounts: - name: tz-config mountPath: /etc/localtime volumes: - name: tz-config hostPath: path: /usr/share/zoneinfo/Asia/Shanghai
我們將/usr/share/zoneinfo/Asia/Shanghai直接掛載為路徑/etc/locatime了。建立該Pod並檢查Pod內的系統時間:
# kubectl create -f 1604-pod-on-1404-host.yamldeployment "my-testpod" created# kubectl exec my-testpod-802169720-ehqlt dateMon Feb 20 14:19:13 CST 2017# dateMon Feb 20 14:19:15 CST 2017
可以看出Pod內的系統時間與Host上的時間在時區上保持一致了。
2、Host 14.04, Pod 14.04
在ubuntu 14.04中,由於/etc/localtime自身就儲存著時區設定,因此我們需要將其mount到Pod的對應位置中。我們的image demo如下:
//1404pod-image-dockerfileFROM ubuntu:14.04CMD ["tail", "-f", "/var/log/bootstrap.log"]
構建該image:
# docker build -f ./1404pod-image-dockerfile -t 1404podimage:latest .Sending build context to Docker daemon 5.632 kBStep 1 : FROM ubuntu:14.04 ---> f2d8ce9fa988Step 2 : CMD tail -f /var/log/bootstrap.log ---> Running in 6815ca6fe9d9 ---> bc7f7de7690dRemoving intermediate container 6815ca6fe9d9Successfully built bc7f7de7690d# docker images|grep 1404pod1404podimage latest bc7f7de7690d 8 seconds ago 187.9 MB
Pod manifest如下:
//1404-pod-on-1404-host.yamlapiVersion: extensions/v1beta1kind: Deploymentmetadata: name: my-testpodspec: replicas: 1 template: metadata: labels: run: my-testpod spec: containers: - name: my-testpod image: 1404podimage:latest imagePullPolicy: IfNotPresent volumeMounts: - name: tz-config mountPath: /etc/localtime volumes: - name: tz-config hostPath: path: /etc/localtime
可以看到,我們將host的/etc/locatime掛載到Pod內的/etc/localtime。建立該Pod後,我們查看一下Pod內的系統時間:
# kubectl exec my-testpod-2443385716-g9d4n dateMon Feb 20 14:44:57 CST 2017# dateMon Feb 20 14:44:59 CST 2017
可以看出:兩者在時區設定上已經一致了。
3、Host 16.04,Pod 16.04
由於有了上面的鋪墊,後續的這兩種情況,鑒於篇幅,我將簡單描述。這裡我們還將利用上面建立的兩個image:1404podimage:latest和1604podimage:latest。
pod的manifest檔案如下:
//1604-pod-on-1604-host.yamlapiVersion: extensions/v1beta1kind: Deploymentmetadata: name: my-testpodspec: replicas: 1 template: metadata: labels: run: my-testpod spec: containers: - name: my-testpod image: 1604podimage:latest imagePullPolicy: IfNotPresent volumeMounts: - name: tz-config mountPath: /etc/localtime volumes: - name: tz-config hostPath: path: /usr/share/zoneinfo/Asia/Shanghai
建立該Pod後,查看系統時間:
# kubectl exec my-testpod-3193072711-7kwdl dateMon Feb 20 14:55:00 CST 2017# dateMon Feb 20 14:55:31 CST 2017
主機和Pod內的系統時間在時區上一致了。
4、Host 16.04,Pod 14.04
pod的manifest檔案如下:
//1404-pod-on-1604-host.yamlapiVersion: extensions/v1beta1kind: Deploymentmetadata: name: my-testpodspec: replicas: 1 template: metadata: labels: run: my-testpod spec: containers: - name: my-testpod image: 1404podimage:latest imagePullPolicy: IfNotPresent volumeMounts: - name: tz-config mountPath: /etc/localtime volumes: - name: tz-config hostPath: path: /usr/share/zoneinfo/Asia/Shanghai
建立該Pod,對比Pod內時間和host時間:
# kubectl exec my-testpod-3024383045-xqbcv dateMon Feb 20 14:58:54 CST 2017# dateMon Feb 20 14:58:49 CST 2017
主機和Pod內的系統時間在時區上一致了。
三、小結
上面所涉及到的manifest檔案和Dockerfile檔案源碼在這裡可以下載到,你可能需要根據你自己的k8s環境做些許改動。
微博:@tonybai_cn
公眾號:iamtonybai
github.com帳號: https://github.com/bigwhite
2017, bigwhite. 著作權.