KubernetesのPodのタイムゾーンをまとめて設定

※2021/2/1追記
PodPresetはv1.20で削除されたようなので使わない方がいいです。
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/service-catalog/pod-preset.md

>PodPresets did not progress out of alpha since 1.6. They were removed in 1.20



# はじめに
Kubernetesで稼働するPodのタイムゾーンはデフォルトでUTCになっています。
タイムゾーンを変更したいときはデプロイするYAMLの中に

```
env:
  - name: TZ
    value: Asia/Tokyo
```

とか書くのが一般的ですが、いちいち書くのが面倒です。

Pod Preset Plays K8S Container Time Zone Automatic Configuration | Develop Paper
https://developpaper.com/pod-preset-plays-k8s-container-time-zone-automatic-configuration/

上記サイトにて[Pod Preset](https://kubernetes.io/ja/docs/concepts/workloads/pods/podpreset/)を用いて、まとめて全Podに設定を投入する方法が紹介されていたので試してみました。

# 環境

```
$ kubectl get node -o wide
NAME        STATUS   ROLES    AGE     VERSION         INTERNAL-IP    EXTERNAL-IP   OS-IMAGE       KERNEL-VERSION     CONTAINER-RUNTIME
k3s-master  Ready    master   3d10h   v1.15.4-k3s.1   192.168.24.2   <none>        Ubuntu 19.04   5.0.0-31-generic   containerd://1.2.8-k3s.1
```

# Pod Preset 有効化
Pod Presetはデフォルトで有効になっていません。

```
$ kubectl get podpresets
error: the server doesn't have a resource type "podpresets"
```

[公式ドキュメント](https://kubernetes.io/ja/docs/concepts/workloads/pods/podpreset/)にKubernetesでの設定方法が記載されていますが、k3sでは異なる方法で設定が必要です。

systemdの設定ファイル、/etc/systemd/system/k3s.serviceを以下のように編集します。

```diff 
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
After=network-online.target

[Service]
Type=notify
EnvironmentFile=/etc/systemd/system/k3s.service.env
ExecStartPre=-/sbin/modprobe br_netfilter
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/k3s \
    server \
	'--no-deploy' \
	'servicelb' \
+	'--kube-apiserver-arg' \
+	'runtime-config=settings.k8s.io/v1alpha1=true' \
+	'--kube-apiserver-arg' \
+	'enable-admission-plugins=PodPreset,NodeRestriction' \

KillMode=process
Delegate=yes
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
TasksMax=infinity
TimeoutStartSec=0
Restart=always
RestartSec=5s

[Install]
WantedBy=multi-user.target
```
編集が終わったらk3sを再起動。

```
$ sudo systemctl daemon-reload
$ sudo systemctl restart k3s
```
※当然ですが、今回のようなシングルノード構成だとrestartしたタイミングで全Podが落ちます。

再起動が終わったのちにpodpresetリソースを確認してみると、

```
$ kubectl get podpreset 
No resources found in default namespace.
```
先ほどとメッセージが変わったことが確認できます。

# タイムゾーン変更用YAMLファイル作成
以下のようなファイルを作成します。

```env-tz-tokyo.yaml
apiVersion: settings.k8s.io/v1alpha1
kind: PodPreset
metadata:
  name: env-tz-tokyo
spec:
  env:
    - name: TZ
      value: Asia/Tokyo
```

# 動作確認
まずは変更前の状態を確認。

```bash
$ kubectl run kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/kubernetes-bootcamp created
$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-7b75749df7-29pxk   1/1     Running   0          3s
$ kubectl exec kubernetes-bootcamp-7b75749df7-29pxk date
Sun Oct 13 13:53:47 UTC 2019
```
UTCになっていることがわかります。

先ほど作ったYAMLファイルをapplyし、

```bash
$ kubectl apply -f env-tz-tokyo.yaml 
podpreset.settings.k8s.io/env-tz-tokyo created
$ kubectl get podpreset
NAME           CREATED AT
env-tz-tokyo   2019-10-13T13:54:49Z
```
一度Podを再起動してから再度確認すると、

```bash
$ kubectl delete pod kubernetes-bootcamp-7b75749df7-29pxk
pod "kubernetes-bootcamp-7b75749df7-29pxk" deleted
$ kubectl get pod
NAME                                   READY   STATUS    RESTARTS   AGE
kubernetes-bootcamp-7b75749df7-4kgt9   1/1     Running   0          53s
$ kubectl exec kubernetes-bootcamp-7b75749df7-4kgt9 date
Sun Oct 13 22:57:21 JST 2019
```
JSTになりました。

# 終わりに
Pod PresetはNamespace毎のリソースなので、default以外のNamespaceでも利用する場合はそれぞれにデプロイすること。

そもそもコンテナのタイムゾーンってどうするのがベストなんでしょうか？
全部UTCにして、時刻を表示する部分のアプリ側で適宜変換するのが適切なような…。