默认情况下,K8S集群里管控的Pod内部时区是UTC0时,跟我们实际所在时区不一致,会导致日志记录等方面存在问题。所以需要使容器内部与宿主机(node节点)的时间保持一致。想要解该问题主要有以下几种思路。

Docker层面时区设置

第一种思路是从docker层面来完成时区设置,其有两种实现方式,分别是通过环境变量以及挂载主机文件方式来完成。以下方式均需保证当前宿主机的时区配置正确。

1、设置容器的时区环境变量

通过在容器启动时,设置环境变量TZ=Asia/Shanghai的方式来实现:

docker run --name=centos -e "TZ=Asia/Shanghai" centos

2、挂载宿主机的时区文件到容器内部

通过在容器启动时,挂载时区文件/etc/localtime为数据卷的方式来实现:

docker run --name=centos -v /etc/localtime:/etc/localtime:ro centos

另外如果是自动打包的镜像,可在dockerfile文件里定义好时区环境变量,生成新的镜像。

K8S层面时区设置

在K8S集群中,也可以参照docker的方式来设置时区。

1、设置环境变量

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

2、挂载主机时区文件

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

3、Pod Preset预设时区信息

前面两种方式虽然可以实现,但是仅仅针对单个Pod有效。对每个Pod都这样设置先得太过繁琐。可以使用K8S的特性Pod Preset从系统层面来实现,在容器启动时自动注入预设的配置信息,这样的话针对同一个命名空间下的所有Pod都会生效。

Pod Preset是API资源,在Pod创建时可以使用它将额外的运行时需求注入到里面。可以使用标签选择器指定Pod Preset用户相应的Pod。使用PodPreset允许pod模板不必为每个pod显式的设置信息。这样pod模板的作者不必知道该服务的所有的详细信息。

  • 激活Pod Preset特性

当前该特性还是alpha阶段,需手动开启。在所有的master节点上,修改/etc/kubernetes/apiserver文件配置,并重启kube-apiserver

①在KUBE_ADMISSION_CONTROL字段增加PodPreset

KUBE_ADMISSION_CONTROL="--admission-control=...,PodPreset"

②在KUBE_API_ARGSd--runtime-config字段增加settings.k8s.io/v1alpha1=true

KUBE_API_ARGS="... --runtime-config=settings.k8s.io/v1alpha1=true"
  • 检验是否开启成功,没开启以前会直接报错
$ kubectl get podpresets
  • 创建设置时区的Pod Preset对象
$ cat allow-tz-env.yaml
apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: allow-tz-env
spec:
  selector:
    matchLabels:
  env:
    - name: TZ
      value: Asia/Shanghai
$ kubectl create -f allow-tz-env.yaml
$ kubectl get podpresets

注意:Pod Preset是namespace级别的对象,其作用范围只能是同一个命名空间下容器。

  • 创建普通容器并验证
apiVersion: v1
kind: Pod
metadata:
  name: pod-no-tz
spec:
  containers:
  - name: mynginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent

THE END.