Kubernetes中如何优雅的解决Pod时区问题

image

1:问题简介

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

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

2:什么是k8tz

k8tz是开源项目:github.com/k8tz/k8tz

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

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

3:部署并使用k8tz

官方提供的是Helm部署:

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

# 这里 --set timezone=<自定义>
查看 Pod 状态、Mutatingwebhookconfigurations、Service 等资源是否正常:
[root@kubernetes-master-1 ~]# kubectl get mutatingwebhookconfigurations.admissionregistration.k8s.io  k8tz
NAME   WEBHOOKS   AGE
k8tz   1          2m20s

[root@kubernetes-master-1 ~]# kubectl get pod -n k8tz 
NAME                  READY   STATUS    RESTARTS   AGE
k8tz-c766b769-2xr7w   1/1     Running   0          109s

[root@kubernetes-master-1 ~]# kubectl get svc -n k8tz 
NAME   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
k8tz   ClusterIP   100.1.124.219   <none>        443/TCP   2m46s

# 测试一个Pod
[root@kubernetes-master-1 ~]# date
Wed Jun 15 23:11:34 CST 2022
[root@kubernetes-master-1 ~]# kubectl exec -it nginx-6fb79bc456-rnsrs /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # date
Wed Jun 15 15:11:44 UTC 2022

# 这里发现 Pod和主机的时区是不同的

# 官方其实提供了三种方式去同步时间,第一种是:InitContainer  第二种就是注解(annotations),第三种就是hostpath,我这里用注解操作

删除原来的测试容器

[root@kubernetes-master-1 ~]# cat nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  annotations:
    k8tz.io/timezone: Asia/Shanghai  # 这里就是写如想要的时区即可
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:alpine
        ports:
        - containerPort: 80

[root@kubernetes-master-1 ~]# kubectl apply -f nginx.yaml 
deployment.apps/nginx created

# 我们可以看一下真个过程
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  13s   default-scheduler  Successfully assigned default/nginx-6fb79bc456-hlnz6 to kubernetes-worker-2
  Normal  Pulling    13s   kubelet            Pulling image "quay.io/k8tz/k8tz:0.5.0"
  Normal  Pulled     2s    kubelet            Successfully pulled image "quay.io/k8tz/k8tz:0.5.0" in 10.57934198s
  Normal  Created    2s    kubelet            Created container k8tz
  Normal  Started    2s    kubelet            Started container k8tz
  Normal  Pulled     1s    kubelet            Container image "nginx:alpine" already present on machine
  Normal  Created    1s    kubelet            Created container nginx
  Normal  Started    1s    kubelet            Started container nginx
# 这里其实也是类似于走了一个 initcontainer的过程

# 查看Pod时区
[root@kubernetes-master-1 ~]# kubectl exec -it nginx-6fb79bc456-hlnz6 /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "nginx" out of: nginx, k8tz (init)
/ # date
Wed Jun 15 23:16:42 CST 2022     # 发现Pod时区已经是在上海了

# 当然了,我们既然能注入时区,当然也可以禁止注入时区,这里可以选择使用注解  k8tz.io/inject: false,但是如果禁止注入时区和注入时区同时出现了,那么注入时区的优先级会比禁止注入时区优先级高

# 下面我们可以使用注解hostpath挂载本地的时区进去    k8tz.io/strategy: hostPath

# 这个其实暂时还不能看出来,因为我主机也是上海
[root@kubernetes-master-1 ~]# kubectl exec -it nginx-6fb79bc456-v75mz /bin/sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
Defaulted container "nginx" out of: nginx, k8tz (init)
/ # date
Wed Jun 15 23:23:48 CST 2022

# annotations 也可以在命名空间中指定,并影响在命名空间中创建的所有 pod。下面创建一个 demo namespace 用于测试:
[root@kubernetes-master-1 ~]# ls | grep nginx
nginx1.yaml
nginx2.yaml
nginx3.yaml
nginx4.yaml
nginx5.yaml
# 这里是5个Pod的yaml

# 创建 ns
[root@kubernetes-master-1 ~]# kubectl create ns demo
namespace/demo created
[root@kubernetes-master-1 ~]# kubectl get ns
NAME              STATUS   AGE
default           Active   41m
demo              Active   5s
---

# 将注解写入ns
k8tz.io/strategy=hostPath
k8tz.io/timezone=Asia/Shanghai

[root@kubernetes-master-1 ~]# kubectl annotate ns demo k8tz.io/strategy=hostPath
namespace/demo annotated
[root@kubernetes-master-1 ~]# kubectl annotate ns demo k8tz.io/timezone=Asia/Shanghai
namespace/demo annotated

# 上面将策略设置为 hostPath 注入方式。因为安装 k8tz 时默认时区已经设置为 Asia/Shanghai,但是Nginx的时区并不是上海,所以这里将 demo namespace 时区设置为 Asia/Shanghai,方便区分。

# 此时创建的 Pod 不需要加任何注解,只要是在这个demo的命名空间下的pod时区都是Asia/Shanghai,接下来测试一下

[root@kubernetes-master-1 ~]# mv *.yaml nginx/
[root@kubernetes-master-1 ~]# ls
anaconda-ks.cfg  nginx
[root@kubernetes-master-1 ~]# ls nginx/
nginx1.yaml  nginx2.yaml  nginx3.yaml  nginx4.yaml  nginx5.yaml
# 创建Pod
[root@kubernetes-master-1 ~]# kubectl apply -f nginx
deployment.apps/nginx1 created
deployment.apps/nginx2 created
deployment.apps/nginx3 created
deployment.apps/nginx4 created
deployment.apps/nginx5 created

[root@kubernetes-master-1 ~]# kubectl get pod -n demo 
NAME                      READY   STATUS    RESTARTS   AGE
nginx1-58fd7d585c-4gt9s   1/1     Running   0          104s
nginx2-6f66b664b6-ngj5h   1/1     Running   0          104s
nginx3-6d8b8c6c-kdd6c     1/1     Running   0          104s
nginx4-7946dfbc9b-57pf6   1/1     Running   0          104s
nginx5-ccc464b49-t6v6z    1/1     Running   0          20s

# 查看时区
[root@kubernetes-master-1 ~]# for i in $(kubectl get pod -n demo | grep -v "NAME" | awk '{print $1}');do kubectl exec -it -n demo $i -- date;done
Wed Jun 15 23:37:23 CST 2022
Wed Jun 15 23:37:23 CST 2022
Wed Jun 15 23:37:23 CST 2022
Wed Jun 15 23:37:23 CST 2022
Wed Jun 15 23:37:24 CST 2022

# 发现时区全部统一了

4:总结

Kubernetes 中的时区问题有多种解决方案,这些解决方案可以手动实现,但在此过程中存在一些挑战和限制。

使用 k8tz可以自动执行该过程,确保系统中所有组件的时区一致,并且所有组件都可以访问有关不同时区的信息。并且无需额外设置或更改现有资源即可工作,即使在节点上没有所需文件时也是如此。
posted @ 2022-06-15 23:42  Layzer  阅读(723)  评论(0编辑  收藏  举报