每日一问 【每日一问】在 k8s 环境下处理容器时间有哪几种方式?

lework · 2022年03月11日 · 72 次阅读

1. 在 Dockerfile 中添加时区

# Set timezone
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
      && echo "Asia/Shanghai" > /etc/timezone

2. 将时区文件挂载到 Pod 中

...
  containers:
  - name: xxx
...
    volumeMounts:
      - name: timezone
        mountPath: /etc/localtime
  volumes:
    - name: timezone
      hostPath:
        path: /usr/share/zoneinfo/Asia/Shanghai

3. 通过环境变量TZ定义时区

...
  containers:
  - name: xxx
...
    env:
    - name: TZ
      value: Asia/Shanghai

4. 通过 PodPreset 全局修改时间

PodPreset可以在容器启动的时候注入一些信息,PodPreset1.20版本后被移除了

# 1.20版本之后 启用 PodPreset
## 在 kube-apiserver 启动参数 -runtime-config 增加 settings.k8s.io/v1alpha1=true;
—runtime-config=rbac.authorization.k8s.io/v1alpha1=true,settings.k8s.io/v1alpha1=true
## 然后在 --admission-control 增加 PodPreset 启用
—admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota,PodPreset

# 查看是否应用上
kubectl api-resources |grep podpresets

#创建PodPresents资源对象
apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: tz-env
spec:
  selector:
    matchLabels:
  env:
  - name: TZ
    values: Asia/Shanghai

5. 调整时间到预设值

pod容器中调整时间,主要原理是在OS层面拦截系统时间欺骗应用,实现返回任意的时间给应用层使用

拦截的主要思路是以动态库的加载为基础的,采用LD_PRELOAD机制,自行实现这个方法并编译成动态库依靠动态库加载的先后顺序来覆盖原始的方法

已经有libfaketime 项目实现,按照其文档,主要步骤为

  • 克隆代码进行编译
git clone https://github.com/wolfcw/libfaketime.git
cd libfaketime  && make install
  • 编译完成后,把库文件拷贝到容器中
docker cp /usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 e6e239e5fba7:/usr/local/lib/
  • 再进入容器中执行命令改变环境变量
export LD_PRELOAD=/usr/local/lib/libfaketime.so.1 FAKETIME="-5d"

容器环境下,手动按照上面的步骤操作是可以生效的,唯一不足的就是一旦容器重启就会失效

在容器 (k8s环境) 中如何解决?

前面的步骤可以将编译完的库文件通过dockerfile打包到镜像中,如果需要修改时间,只需要在Pod控制器定义时添加环境变量即可

...
  containers:
  - name: xxx
...
    env:
    - name: LD_PRELOAD
      value: "/usr/local/lib/libfaketime.so.1"
    - name: FAKETIME
      value: "-5d"

另外一种思路是,时间调整一般是暂时的,以及多pod时间同步的需求,将LD_PRELOAD的打开与否放到应用的运行环境中,采用configmap作为应用时间的标准,将时间变更值faketime作为configmap

apiVersion: v1
kind: ConfigMap
metadata:
  name: faketimerc
  namespace: default
data:
  faketimerc: |
    +10d

最后所有的pod都以volume的形式挂载该configmap

...
  containers:
  - name: xxx
...
    volumeMounts:
      - name: faketimerc
        mountPath: /etc/faketimerc
  volumes:
    - name: faketimerc
      configMap:
        name: faketimerc
        items:
        - key: faketimerc
          path: faketimerc
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册