nanasi-apps.xyz

Immich をk8sに構築する

公開日: 2025/3/9
Open Source

知り合いがImmichをセルフホストしてるのを見て気になったので自分でも建ててみました。

その時にk8s初心者ながら困ったことをつらつらと書いていこうと思います。

文章の整理を効率化するため、ChatGPTとNotionAIを使用して文章を校正しているので、表現が少し不自然かもしれません。

0. K8s(k0s)構築編

特に困ったことはありませんでした。

K0sというk8sクラスタを簡単に構築できるソフトウェアを使用しました。

ただし、本番環境での使用については検討が必要なため、今後調査する予定です。

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を使用してデプロイする方法があることがわかりました。helm install --create-namespace --namespace immich immich immich/immich -f values.yaml

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

ただし、

こちらの情報によると、PostgreSQLは別途自分でセットアップする必要があります。

そこで、これも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

上記の2つのドキュメントを参照すれば、手順は理解できるはずです。

インストール方法は2つあり、

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

私はDirect Install方式を選択したので、以下ではその手順を説明します。

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

驚くことに、上記のコマンドを入力するだけで完了です。

とても簡単ですね。

次に、公式の指示に従って一度テストデプロイを実行してみましょう。

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

  storage:
    size: 1Gi

これが正常にデプロイできたら問題ないと判断できます。

一度このテスト用デプロイメントを削除してから、本番用のデプロイメントを実行します。

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の場合、同じ値を入力します。

  1. 以下の設定はデフォルトのままにします:

・特権設定

・Squash設定(変更すると問題が発生する可能性があります)

・セキュリティ設定

  1. 「非優先ポートからの接続」と「マウントしたサブフォルダへのアクセスを許可する」にチェックを入れます。
  2. 設定を保存します。
  3. 左下に表示されるマウントパスは後で必要になるのでメモしておきます。

次に、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を作成します。

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

このような形でPersistent VolumeとPersistent Volume Claimsを作成できます。

1.3 Immichの構築

これで準備が整いましたので、Immichの構築に進めます。

values.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 コマンドを実行して待つだけでデプロイが完了するはずです。

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

困ったこと

NFSの設定を変更しすぎて権限関係が複雑になり、トラブルに

SynologyのNFSでSquashの設定をいじらない方がいいと書いたのは、この問題で2時間も苦労したからです!

もしファイルの権限回りが変になったりしたら

NFSの設定を直して、すべてを削除してから再デプロイするのがベストです。

また、Storage Classesなどのストレージ関連の設定を変更した場合も、すべてを一度削除してから再デプロイする必要があります。

私の環境では、この方法でしか問題を解決できませんでした。