跳到主要内容

k8s-timezone

容器在主机的内核上运行,并获得时钟,但时区不是来自内核,而是来自用户空间。在大多数情况下,默认使用协调世界时 (UTC)。

时区的不一致,会带来很多困扰。即使代码与时区无关,但容器日志与系统日志时间相关联排查问题也会让人头疼。一些应用程序使用机器的时区作为默认时区,并希望用户设置时区。当集群中容器的时区不一致时,会出现问题。

Dockerfile 中配置

通过编写 Dockerfile,构建自己的 Docker 镜像,可以永久解决时区问题。

1. Alpine

ENV TZ Asia/Shanghai

RUN apk add tzdata && cp /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone \
&& apk del tzdata

2. Debian

Debian 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中:

ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive

RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata \
&& rm -rf /var/lib/apt/lists/*

3. Ubuntu

Ubuntu 基础镜像中没有安装了 tzdata 包,因此我们需要先安装 tzdata 包。 我们可以将以下代码添加到 Dockerfile 中。

ENV TZ=Asia/Shanghai \
DEBIAN_FRONTEND=noninteractive

RUN apt update \
&& apt install -y tzdata \
&& ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata \
&& rm -rf /var/lib/apt/lists/*

4. CentOS

CentOS 基础镜像 中已经安装了 tzdata 包,我们可以将以下代码添加到 Dockerfile 中。

ENV TZ Asia/Shanghai

RUN ln -fs /usr/share/zoneinfo/${TZ} /etc/localtime \
&& echo ${TZ} > /etc/timezone

podDeployment 中配置

      containers:
- name: test
image: ubuntu:20.04
volumeMounts:
- name: localtime
mountPath: /etc/localtime
volumes:
- name: localtime
hostPath:
path: /etc/localtime

使用 k8tz 设置

k8tz是一个 Kubernetes 准入控制器和一个将时区注入 Pod 的 CLI 工具。 可以用作手动工具来自动转换 Deployment 和 Pod 可以作为准入控制器安装并使用注释来完全自动化创建 Pod 的过程。

k8tz 可以使用 hostPath的方式,或者将 emptyDir 注入 initContainer并用 TZif(时区信息格式) 文件填充卷。然后将 emptyDir挂载到 Pod 每个容器的 /etc/localtime/usr/share/zoneinfo。为了确保所需的时区有效,它向所有容器添加了 TZ环境变量。

install

使用 helm 安装

helm repo add k8tz https://k8tz.github.io/k8tz/
helm install k8tz k8tz/k8tz --set timezone=Asia/Shanghai

查看 Pod 状态、Mutatingwebhookconfigurations、Service 等资源是否正常:

# kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io  k8tz
NAME WEBHOOKS AGE
k8tz 1 7h5m

# kubectl get svc -n k8tz
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
k8tz ClusterIP 10.98.114.250 <none> 443/TCP 7h5m


# kubectl get pod -n k8tz
NAME READY STATUS RESTARTS AGE
k8tz-649f85c78d-9lxrq 1/1 Running 0 16m

测试

kubectl run -i -t ubuntu --image=ubuntu:22.04 --restart=OnFailure --rm=true --command date
Defaulted container "ubuntu" out of: ubuntu, k8tz (init)
Wed Jul 27 17:35:06 CST 2022
pod "ubuntu" deleted

使用