nanasi-apps.xyz

K0s で Kubernetes クラスタを構築する。

公開日: 2025/3/9

知り合いがImmichをセルフホストしているのを見て興味を持ったので、自分でも構築してみました。

k8s初心者として遭遇した課題を順番に説明していきます。

0. K8s(k0s)構築編

k8sのクラスタを簡単に構築できるK0sというソフトウェアを使用しました。構築自体は特に問題なく進みましたが、本番環境での使用については後ほど調査が必要そうです。

1. Immich構築

この作業には約4時間かかりました。

公式ドキュメントのKubernetesセクションには、

You can deploy Immich on Kubernetes using the official Helm chart.

You can view some examples of how other people run Immich on Kubernetes, using the official chart or otherwise.

という簡単な説明しかないため、かなり苦労しました。

[公式の手順では

helm

を使用してデプロイするようです。](https://github.com/immich-app/immich-charts/blob/main/README.md)

helm install --create-namespace --namespace immich immich immich/immich -f values.yaml

というコマンドを使用します。

ただし、[

PostgreSQL

は別途自分でセットアップする必要があります。](https://github.com/immich-app/immich-charts/issues/149)

これもK8s上に構築することにしました。

1.1 PostgreSQL構築(Cloudnative PGの構築)

幸いなことに、上記のGitHub Issueに解決策が記載されていました。

https://github.com/immich-app/immich-charts/issues/149#issuecomment-2671165919

cloudnative PG

を使用することで効率的に構築できます。

以下の公式ドキュメントを参照すれば、手順は明確です:

https://github.com/cloudnative-pg/cloudnative-pg/blob/main/docs/src/installation_upgrade.md

https://github.com/cloudnative-pg/cloudnative-pg/blob/main/docs/src/quickstart.md#part-3-deploy-a-postgresql-cluster

Helmを使用する場合はこちらのドキュメントを参照してください。

私は

Direct Install

方式で構築しましたので、その手順を説明します。

curl -sSfL \
  https://raw.githubusercontent.com/cloudnative-pg/artifacts/main/manifests/operator-manifest.yaml | \
  kubectl apply --server-side -f -

このコマンド一つで基本的なセットアップが完了します。

次に、公式の手順に従ってテスト用のデプロイを行います。

yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example
spec:
  instances: 3

  storage:
    size: 1Gi

このテストデプロイが成功したら、実際の環境用の設定に移ります。

テスト環境を削除した後、本番用の設定をデプロイします:

yaml
kind: Cluster
metadata:
  name: immich-postgres
spec:
  # At the time of writing, immich is only compatible with pgvecto.rs <0.4. Latest postgres image with that version is 16.5.
  imageName: ghcr.io/tensorchord/cloudnative-pgvecto.rs:16.5-v0.3.0@sha256:be3f025d79aa1b747817f478e07e71be43236e14d00d8a9eb3914146245035ba
  instances: 1

  postgresql:
    shared_preload_libraries:
      - "vectors.so"

  managed:
    roles:
      - name: immich
        superuser: true
        login: true

  bootstrap:
    initdb:
      database: immich
      owner: immich
      secret:
        name: immich-postgres-user
      postInitSQL:
        - CREATE EXTENSION IF NOT EXISTS "vectors";
        - CREATE EXTENSION IF NOT EXISTS "cube" CASCADE;
        - CREATE EXTENSION IF NOT EXISTS "earthdistance" CASCADE;

  storage:
    size: 4Gi
    storageClass: immich-postgres
---
apiVersion: v1
kind: Secret
metadata:
  name: immich-postgres-user
  namespace: immich-new
type: Opaque
stringData:
  username: immich
  password: "FIXME"

パスワードの「FIXME」を適切な値に変更してからデプロイしてください。

ここまでの設定が完了しても、まだImmichのデプロイには進めません。

1.2 PVCのデプロイ

私はSynologyのNASをNFSで接続して使用しました。この設定が最も苦労した部分です。

前提条件:

  • NAS側のボリュームと共有フォルダが既に作成されていること

設定手順:

  1. NASのコントロールパネルから共有フォルダを開きます
  2. K8sのストレージとして使用するフォルダを選択して「編集」をクリックします
  3. 「NFS権限」タブを選択します
  4. NFSサービスの有効化を求められた場合は、指示に従います
  5. 「作成」を選択します
ホスト名または IP

欄には、割り当てているローカルIPの範囲を入力します。

例えば、サーバーのIPが

192.168.2.0/24

の範囲にある場合は、

192.168.2.0/24

と入力します。

以下の設定はデフォルトのままにしておきます:

  • 特権
  • Squash(理解できない場合は変更しないでください - 私は2時間も無駄にしました)
  • セキュリティ

「非優先ポートからの接続」と「マウントしたサブフォルダへのアクセスを許可する」にはチェックを入れます。

設定が完了したら保存します。その後、画面左下に表示されているマウントパスをメモしておきます。

続いて、k8s側でNFSを使用できるように設定します。

まず、NFSパッケージをインストールします:

sudo apt install nfs-common

その後、以下のコマンドでNFSプロビジョナーをセットアップします:

helm install nfs-provisioner nfs-provisioner/nfs-provisioner   --set nfs.server={NASのIP} --set nfs.path={マウントパス} --set storageClass.name=nas-storage --set storageClass.defaultClass=true

他の方法でも設定は可能です。

次に、Persistent VolumeとPersistent Volume Claimsを作成します:

yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: immich
  namespace: immich
spec:
  capacity:
    storage: {容量の}
  nfs:
    server: {NASのIP}
    path: {マウントパス}
  accessModes:
    - ReadWriteMany
  storageClassName: nas-storage
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: immich-pvc
  namespace: immich
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Gi
  volumeName: immich
  storageClassName: nas-storage

これで基本的なストレージ設定は完了です。

1.3 Immichの構築

準備が整ったので、最後にImmichをデプロイします。

values.yaml

の設定について:

公式の設定例はこちらにあります。

以下は私が使用した設定です(ほぼ公式の設定をそのまま使用):

yaml
env:
  REDIS_HOSTNAME: '{{ printf "%s-redis-master" .Release.Name }}'
  DB_HOSTNAME: immich-postgres-rw.immich.svc.cluster.local
  DB_USERNAME:
    secretKeyRef:
      name: immich-postgres-user
      key: username
  DB_DATABASE_NAME: immich
  DB_PASSWORD:
    secretKeyRef:
      name: immich-postgres-user
      key: password
  IMMICH_MACHINE_LEARNING_URL: '{{ printf "http://%s-machine-learning:3003" .Release.Name }}'

image:
  tag: v1.11

immich:
  metrics:
    # Enabling this will create the service monitors needed to monitor immich with the prometheus operator
    enabled: false
  persistence:
    # Main data store for all photos shared between different components.
    library:
      # Automatically creating the library volume is not supported by this chart
      # You have to specify an existing PVC to use
      existingClaim: immich-pvc
  trash:
      enabled: true
      days: 30

# Dependencies

redis:
  enabled: true
  architecture: standalone
  auth:
    enabled: false

# Immich components

server:
  enabled: true
  image:
    repository: ghcr.io/immich-app/immich-server
    pullPolicy: IfNotPresent
  ingress:
    main:
      enabled: false
      annotations:
        # proxy-body-size is set to 0 to remove the body limit on file uploads
        nginx.ingress.kubernetes.io/proxy-body-size: "0"
      hosts:
        - host: immich.local
          paths:
            - path: "/"
      tls: []

machine-learning:
  enabled: true
  image:
    repository: ghcr.io/immich-app/immich-machine-learning
    pullPolicy: IfNotPresent
  env:
    TRANSFORMERS_CACHE: /cache
  persistence:
    cache:
      enabled: true
      size: 10Gi
      # Optional: Set this to pvc to avoid downloading the ML models every start.
      type: emptyDir
      accessMode: ReadWriteMany
      # storageClass: your-class

この設定を保存したら、以下のコマンドでデプロイします:

helm install --create-namespace --namespace immich immich immich/immich -f values.yaml

困ったこと

NFSの設定における権限の問題

SynologyのNFSでSquash設定を変更したことで2時間もトラブルシューティングに費やしました。この設定は変更しないことを強く推奨します。

ファイルの権限に問題が発生した場合

問題が発生した場合は以下の手順を推奨します:

  1. NFSの設定を適切な状態に戻す
  2. すべてのリソースを削除する
  3. 最初から再デプロイする

特に、Storage Classesやストレージ関連の設定を変更した後は、必ずすべてのリソースを削除してから再デプロイしなおすことを推奨します。