轉載自:https://cloud.tencent.com/developer/article/1433215
1、背景介紹
我們知道,使用 docker 容器啟動服務后,如果使用默認 Centos 系統作為基礎鏡像,就會出現系統時區不一致的問題,因為默認 Centos 系統時間為 UTC 協調世界時 (Universal Time Coordinated),一般本地所屬時區為 CST(+8 時區,上海時間),時間上剛好相差 8 個小時。這就導致了,我們服務啟動后,獲取系統時間來進行相關操作,例如存入數據庫、時間換算、日志記錄等,都會出現時間不一致的問題,所以很有必要解決掉容器內時區不統一的問題。
問題顯示如下:
# 查看本地時間
$ date
Wed Mar 6 16:41:08 CST 2019
# 查看容器內 centos 系統默認時區
$ docker run -it centos /bin/sh
sh-4.2# date
Wed Mar 6 08:41:45 UTC 2019
2、環境、軟件准備
本次演示環境,我是在虛擬機上安裝 Linux 系統來執行操作,通過虛擬機完成 Kubernetes 集群的搭建,以下是安裝的軟件及版本:
- Oracle VirtualBox: 5.1.20 r114628 (Qt5.6.2)
- System: CentOS Linux release 7.3.1611 (Core)
- kubernetes: 1.12.1
- docker: 18.06.1-ce
注意:本次操作基於 Linux Centos7 系統操作,若系統為 Ubuntu 或其他 Linux 系統,亦可參考方案對應處理,都大同小異。
3、Dockerfile 中處理
可以直接修改 Dockerfile
,在構建系統基礎鏡像或者基於基礎鏡像再次構建業務鏡像時,添加時區修改配置即可。
$ cat Dockerfile.date
FROM centos
RUN rm -f /etc/localtime \
&& ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
# 構建容器鏡像
$ docker build -t centos7-date:test -f Dockerfile.date .
Sending build context to Docker daemon 4.426GB
Step 1/2 : FROM centos
---> 1e1148e4cc2c
Step 2/2 : RUN rm -f /etc/localtime && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone
---> Running in fe2e931c3cf2
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Shanghai'
Removing intermediate container fe2e931c3cf2
---> 2120143141c8
Successfully built 2120143141c8
Successfully tagged centos7-date:test
$ docker run -it centos7-date:test /bin/sh
sh-4.2# date
Wed Mar 6 16:40:01 CST 2019
可以看到,系統時間正常了,個人比較推薦這種方式,一勞永逸,只需要一次配置即可,后續在基於此基礎鏡像制作的鏡像就可以直接使用了,不需要擔心時區問題。
4、容器啟動時處理
除了在 Dockerfile 中修改配置方式外,我們還可以在容器啟動時通過掛載主機時區配置到容器內,前提是主機時區配置文件正常。
# 掛載本地 /etc/localtime 到容器內覆蓋配置
$ docker run -it -v /etc/localtime:/etc/localtime centos /bin/sh
sh-4.2# date
Wed Mar 6 16:42:38 CST 2019
# 或者掛載本地 /usr/share/zoneinfo/Asia/Shanghai 到容器內覆蓋配置
$ docker run -it -v /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime centos /bin/sh
sh-4.2# date
Wed Mar 6 16:42:52 CST 2019
以上兩種方式,其實原理都一樣,在 Centos 系統中,/usr/share/zoneinfo/Asia/Shanghai
和 /etc/localtime
二者是一致的,我們一般會將二者軟連接或者直接 cp 覆蓋。
5、進入容器內處理
還有一種方式,就是進入到容器內處理,但是此方式有個不好的地方就是,如果容器刪除后重新啟動新的容器,還需要我們進入到容器內配置,非常不方便,所以個人不建議此方式。
# 進入到容器內部配置
$ docker run -it centos /bin/sh
sh-4.2# date
Wed Mar 6 08:43:29 UTC 2019
sh-4.2# rm -f /etc/localtime && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
'/etc/localtime' -> '/usr/share/zoneinfo/Asia/Shanghai'
sh-4.2# date
Wed Mar 6 16:43:54 CST 2019
6、k8s 解決容器時間不一致
在 K8s 集群里,也會存在因為時區不一致導致的問題,還記得我之前文章中挖出來的坑 配置 Ceph Object Gateway Management Frontend 中,因為容器時間不一致,導致的報錯。那么在 k8s 集群里,如何解決容器時間不統一的問題呢?方式有很多,最一勞永逸的方式還是上邊,在基礎鏡像或者服務鏡像里面直接配置好。其次我們還可以通過掛載主機時間配置的方式解決,針對此方式,我舉個栗子。
$ cat busy-box-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: busy-box-test
namespace: default
spec:
restartPolicy: OnFailure
containers:
- name: busy-box-test
image: busybox
imagePullPolicy: IfNotPresent
volumeMounts:
- name: date-config
mountPath: /etc/localtime
command: ["sleep", "60000"]
volumes:
- name: date-config
hostPath:
path: /etc/localtime
注意:如果主機 /etc/localtime
已存在且時區正確的話,可以直接掛載,如果本地 /etc/localtime
不存在或時區不正確的話,那么可以直接掛載 /usr/share/zoneinfo/Asia/Shanghai
到容器內 /etc/localtime
,都是可行的。