【问题小解决】解决容器内时区不一致问题


业务程序在使用时间的时候(比如打印日志),没有指定时区,使用的系统默认时区, 而基础镜像一般默认使用 UTC 时间,程序输出时间戳的时候,就与国内的时间相差 8 小时。

游戏全球对战服场景这个问题更要命,开发需要通过时间计算同步帧的偏移量,如果这个时候还要重新计算时区是非常浪费计算资源的(-_-)

方案一:指定 TZ 环境变量

很多编程语言都支持TZ这个用于设置时区的环境变量,可以在部署工作负载的时候,为容器指定该环境变量,示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app
          image: app
          env: # 关键
            - name: TZ
              value: Asia/Shanghai

方案二:Dockerfile 里设置时区

下面给出在一些常见的基础镜像里设置时区的实例。

Ubuntu 镜像:

1
2
3
4
5
6
FROM ubuntu:latest

RUN apt update -y && \
  DEBIAN_FRONTEND="noninteractive" apt -y install tzdata
RUN ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
  dpkg-reconfigure -f noninteractive tzdata

Alpine 镜像:

1
2
3
4
5
6
7
FROM alpine:latest

# 安装 tzdata,复制里面的时区文件后删除 tzdata,保持精简
RUN apk add --no-cache tzdata && \
  cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
  apk del tzdata && \
  echo "Asia/Shanghai" > /etc/timezone

CentOS 镜像:

1
2
3
4
5
FROM centos:latest

RUN rm -f /etc/localtime \
  && ln -sv /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
  && echo "Asia/Shanghai" > /etc/timezone

方案三:挂载主机时区配置到容器(不推荐)

最后一种思路是将 Pod 所在节点的时区文件挂载到容器内 /etc/localtime,这种方式对 Pod 有一定侵入性,而且依赖主机内时区配置,在不得已的情况下不推荐使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
        - name: app
          image: app
          volumeMounts:
            - name: tz
              mountPath: /etc/localtime
      volumes:
        - name: tz
          hostPath:
            path: /etc/localtime