おうちk8s進捗: Volumeの使い方を学んだ

おうちk8sをはじめて2ヶ月が経過したが進捗がなく、涙 に書いたように、おうちk8sに憧れてなんとなくマシンを3台買ったのにあんまり活用できてなかったので、進捗を出そうと頑張った記録です。

進捗報告まとめ

  • linkdingというBookmarkサービスをおうちk8sにデプロイした
  • 最初に小さな構成としてVolumeはemptyDirを使った
  • 次にVolumeをPVCに変更しようと思い、PVを作成するためのソフトウェアを調べた
  • longhornを選択して、Talos Linuxとlonghornが噛み合うように設定した
  • longhornを動かすことに成功して、linkdingのVolumeをPVCに変更できた

前回の振り返り

前回の記事: おうちk8sをはじめて2ヶ月が経過したが進捗がなく、涙

前回のgerritを立てるところで詰まった原因は、「helmで詰まるとやばい」ところにある。特にVolume周りの知識がない状態だと、アプリケーション起因でうまく立ち上がらないのか、それともVolume周りの設定起因なのかの切り分けが難しく結局断念した。

そこで今回は、もっとシンプルなサービスを、helmなどを使わずにデプロイすることでVolume自体の学習に集中する。

linkdingについて

sissbruecker/linkding はミニマルなBookmarkサービスで、DBはsqliteを使っている。

installationにdockerでのセットアップが書かれている

docker run --name linkding -p 9090:9090 -v {host-data-folder}:/etc/linkding/data -d sissbruecker/linkding:latest

まずはこれを参考に動かしてアプリ側で詰まらないようにしておく。

  • /etc/linkding/data にsqliteのデータが保存されてそう(ref. Backups)
  • ポートは9090番で動作する
  • 初期ユーザは環境変数で LD_SUPERUSER_NAMELD_SUPERUSER_PASSWORD で設定できる (ref. Options)

k8sのVolumeについておさらい

Volumes | Kubernetes を眺めると、Volumeは共有ストレージのようなもので、Podがクラッシュした時に状態が失われる問題と、複数コンテナ間でファイルを共有できない問題を解決する機能になっている。

VolumeにはTypeがある。今回関連するのは以下のType。

  • configMap: 設定をPodに注入するために使う。環境変数とか設定ファイルとか。
  • emptyDir: Podに紐付く。Podと同じライフサイクルなのでPodが削除されるとデータも消える。
  • persistentVolumeClaim(PVC): PersistentVolume(PV)リソースをPodにマウントする。PVはPodとは別のリソースなので、Podが削除されてもデータは失われない。

記録

linkdingをおうちk8s上で動かす

まずシンプルな構成で動かすことにする。linkdingのCommunity を眺めるとk8s manifest例があったのでそれを見る。

manifest例 linkding-k8s-s3 をみると、litestreamというSQLite用のレプリケーションツールを使ってemptyDirに置いたsqliteのデータをS3へバックアップする方針を取っている。

今回はS3は使わないので、litestreamに関する部分を消した。
以下の部分は参考にできそう。

    spec:
      volumes:
        - name: data
          emptyDir: {}

一個一個調べながら書いていく。

kubectl apply -f manifest.yaml でデプロイした。
Podの様子はRunningになってそう。大丈夫。

続いて外からアクセスするためにTailscaleで繋ぐ。
Kubernetes operator · Tailscale Docs を参考にして、helm upgradeする

$ helm upgrade \
  --install \
  tailscale-operator \
  tailscale/tailscale-operator \
  --namespace=linkding \ 
  --set-string oauth.clientId="xx" \ 
  --set-string oauth.clientSecret="xx" \
  --wait

Release "tailscale-operator" does not exist. Installing it now.
Error: Unable to continue with install: CustomResourceDefinition "connectors.tailscale.com" in namespace "" exists and cannot be imported into the current release: invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "linkding": current value is "gerrit-operator"

エラーが出た。
kubectl get crd connectors.tailscale.com -o yaml を叩いてみると、確かにこの前消したはずのgerrit-operatorがいる

$ kubectl get crd connectors.tailscale.com -o yaml

metadata:
  annotations:
	  meta.helm.sh/release-name: tailscale-operator
    meta.helm.sh/release-namespace: gerrit-operator

release-namespaceがよく分かっていない。後から思ったけどこれはNamespaceごとにデプロイするものじゃなくて、"tailscale-system"みたいなNamespaceにデプロイして他のNamespaceから参照するものなのか?

この時は以下の手順で消していった

kubectl get crds -oname | grep "tailscale" | xargs kubectl delete
kubectl get clusterrole -oname | grep "tailscale" | xargs kubectl delete
kubectl get clusterrolebinding -oname | grep "tailscale" | xargs kubectl delete
kubectl get ingressclass -oname | grep "tailscale" | xargs kubectl delete

これでようやく helm upgrade が動く

$ kubectl -n linkding describe ing ingress-linkding-tailscale
Name:             ingress-linkding-tailscale
Labels:           <none>
Namespace:        linkding
Address:          <tailscaleから払い出されたドメイン>
Ingress Class:    tailscale
Default backend:  <default>
TLS:
  SNI routes linkding
Rules:
  Host        Path  Backends
  ----        ----  --------
  *           
              /   linkding:80 (*.*.*.*:9090)
Annotations:  <none>
Events:       <none>

これでURLにアクセスしたらlinkdingが見れた。

この時のcommit: c9c2853684392e9514e994a72155f008aa7f9bc2

  • emptyDirを使っている
  • tailscaleで外に出ている

これでシンプルな構成ができた。

Talos Linuxとlonghornの設定

次はPVCを使いたい。
調べてみたところ、longhornが良さそうだったのでこれをデプロイする。

helmはもしヤバくなった時にデバッグできる自信がないので、 Install with Kubectl のドキュメントを見ながらやっていく。

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.7.2/deploy/longhorn.yaml

applyしたら、11分立ってもinitが終わらない。ドキュメントをみると2分くらいで立ちそうな見た目をしているのでおかしいと思い、キャンセル
調べてみると、Talos Linuxの場合は Talos Linux Support の手順を踏む必要があった。

やることは3つ

  • System ExtensionsをTalos LinuxのOS設定に追加
  • Pod Security Admissionを enforce: privileged に変更
  • Data path mountsを設定

ちなみにうまくいっていない時の状態はこんな感じになったりする。extraMounts設定をして、Pod Securityも設定して、Extensionがない状態だとこんな感じ。

$ kubectl get pods \
--namespace longhorn-system \
--watch
NAME                                        READY   STATUS             RESTARTS      AGE
longhorn-driver-deployer-57c5fd5677-9tk4w   0/1     Init:0/1           0             23s
longhorn-manager-fnjgn                      1/2     CrashLoopBackOff   1 (7s ago)    23s
longhorn-manager-mpl9n                      1/2     CrashLoopBackOff   1 (16s ago)   23s
longhorn-ui-d476cbd9d-t4fsx                 1/1     Running            0             23s
longhorn-ui-d476cbd9d-trjmq                 1/1     Running            0             23s
longhorn-manager-mpl9n                      1/2     Error              2 (19s ago)   26s
longhorn-manager-mpl9n                      1/2     CrashLoopBackOff   2 (5s ago)    31s
longhorn-manager-fnjgn                      1/2     Error              2 (19s ago)   35s
longhorn-manager-fnjgn                      1/2     CrashLoopBackOff   2 (6s ago)    41s

System Extensionsの設定

Extensionsが入ってない状態だった。

$ talosctl get extensions --nodes <IP> --endpoints <IP> --talosconfig=./talosconfig
NODE   NAMESPACE   TYPE   ID   VERSION   NAME   VERSION

最初は talosctl apply-config でいけるかと考えていた。

customization:
  systemExtensions:
    officialExtensions:
      - siderolabs/iscsi-tools
      - siderolabs/util-linux-tools

この変更を machine.install.image に反映させて talosctl apply-config

$ talosctl apply-config -f controlplane.yaml --nodes <IP> --endpoints <IP> --talosconfig=./talosconfig
Applied configuration without a reboot

rebootをする

$ talosctl reboot --nodes <IP> --endpoints <IP> --talosconfig=./talosconfig
watching nodes: [<IP>]
    * <IP>: post check passed

でもExntensionsが入ってない。

色々やった結果、「installerはupgrade時にiso入れ替えが起こるタイミングで使用される」ということが分かった。
そこで talosctl upgrade を実行

$ talosctl upgrade --nodes <IP> --endpoints <IP> --talosconfig=./talosconfig --preserve --image='factory.talos.
dev/installer/613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245:v1.8.3'
WARNING: <IP>: server version 1.7.6 is older than client version 1.8.3
watching nodes: [<IP>]
    * <IP>: post check passed

(本当は色々紆余曲折あったが割愛、preserveつけずにやったらデータ破壊したりして大変だった)

これでExtensionsが入った

[22:22:18] uta8a@rustacean: infra/home-k8s 🌱 learn-volume 
$ talosctl get extensions --nodes <IP>,<IP>,<IP> --endpoints <IP> --talosconfig=./talosconfig

NODE            NAMESPACE   TYPE              ID   VERSION   NAME               VERSION
<IP>   runtime     ExtensionStatus   0    1         iscsi-tools        v0.1.6
<IP>   runtime     ExtensionStatus   1    1         util-linux-tools   2.40.2
<IP>   runtime     ExtensionStatus   2    1         schematic          613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245
<IP>   runtime     ExtensionStatus   0    1         iscsi-tools        v0.1.6
<IP>   runtime     ExtensionStatus   1    1         util-linux-tools   2.40.2
<IP>   runtime     ExtensionStatus   2    1         schematic          613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245
<IP>   runtime     ExtensionStatus   0    1         iscsi-tools        v0.1.6
<IP>   runtime     ExtensionStatus   1    1         util-linux-tools   2.40.2
<IP>   runtime     ExtensionStatus   2    1         schematic          613e1592b2da41ae5e265e8789429f22e121aab91cb4deb6bc3c0b6262961245

extraMountsの設定

commit: 8609f0d5f0d05d91e866535c6610ad22f0079f2b

多分workerだけでいい気もするが、設定した

Pod Security Admissionの設定

commit: e2be62ca1b83e9f6a9f975cb7e411b3169ad343c

フォーマッタが入っているが、実質差分はこちらのlabelsのみ

kind: Namespace
metadata:
  name: longhorn-system
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/audit-version: latest
    pod-security.kubernetes.io/warn: privileged
    pod-security.kubernetes.io/warn-version: latest

これでlonghornが動作した。

$ kubectl -n longhorn-system get pods                                        
NAME                                                READY   STATUS    RESTARTS        AGE
csi-attacher-698944d5b-kzn8t                        1/1     Running   0               5m5s
csi-attacher-698944d5b-ld2qm                        1/1     Running   0               6m42s
csi-attacher-698944d5b-lmpzx                        1/1     Running   1 (112s ago)    5m4s
csi-provisioner-b98c99578-62j64                     1/1     Running   1 (112s ago)    6m42s
csi-provisioner-b98c99578-vkrqg                     1/1     Running   0               5m5s
csi-provisioner-b98c99578-zrbq8                     1/1     Running   0               5m5s
csi-resizer-7474b7b598-7gl8r                        1/1     Running   0               5m4s
csi-resizer-7474b7b598-7wkcq                        1/1     Running   1 (112s ago)    5m4s
csi-resizer-7474b7b598-r9mmh                        1/1     Running   0               6m42s
csi-snapshotter-774467fdc7-64m47                    1/1     Running   0               5m3s
csi-snapshotter-774467fdc7-7grv5                    1/1     Running   1 (115s ago)    6m42s
csi-snapshotter-774467fdc7-lznwq                    1/1     Running   0               5m4s
engine-image-ei-51cc7b9c-hgqkk                      1/1     Running   0               7m17s
engine-image-ei-51cc7b9c-wcp8x                      1/1     Running   0               3m28s
instance-manager-3a87944663e094a108abea000e1186d3   1/1     Running   0               6m47s
instance-manager-433e3e043ebf59e3e5a6f8d1885b8705   1/1     Running   0               2m41s
longhorn-csi-plugin-pkf6n                           3/3     Running   0               6m42s
longhorn-csi-plugin-prk54                           3/3     Running   2 (3m11s ago)   3m28s
longhorn-driver-deployer-57c5fd5677-977zd           1/1     Running   0               5m3s
longhorn-manager-25slx                              2/2     Running   0               3m28s
longhorn-manager-sbv4m                              2/2     Running   0               7m39s
longhorn-ui-d476cbd9d-l57qq                         1/1     Running   0               5m5s
longhorn-ui-d476cbd9d-lrvnv                         1/1     Running   0               5m3s

emptyDirからPVCに変更してapply

kubectl apply -f ./manifest.yaml

commit: 6de6cd0b299938bb22eeb733ceb1aa81cb174410

(secretはsecrets.yamlを作ってそこに書き込むなどかなり雑にやっている)

できた!ちゃんとPodを消してもデータが残る。

linkding

感想

  • PVC, PVを使い方の側面から理解した
  • Talos Linuxは難しい
  • 次はまた別のサービスに挑戦したい(CI/CD, Observabilityあたりが気になっている)
  • Identity Aware Proxyをマネージドで借りて自宅サーバの前段において、認証が通った人のみ自作サーバにアクセスできる環境を作ってみたい。おうちクラウドみたいなのを作って、友人に一部のリソースを貸し出すみたいなのも作れそう。