--- title: 自宅サーバーにK3sとSynology CSI Driverをインストールメモ tags: ["Kubernetes", "K3s", "Synology CSI Driver", "Synology", "NAS", "Home Lab"] categories: ["Dev", "CaaS", "Kubernetes", "K3s"] date: 2025-11-28T10:51:21Z updated: 2025-11-28T10:55:43Z --- 今まで自宅サーバーにはMicrok8sをインストールしてKubernetesクラスターを構築していましたが、今回はK3sをインストールしてみたので、そのメモ。 [Synology CSI Driver](https://github.com/SynologyOpenSource/synology-csi)を使いたかったのですが、Microk8sだとうまく動作しなかったので、実績のあるK3sを試してみました。 Controlplane(兼Worker)ノード1台(192.168.100.50)、Workerノード2台(192.168.100.51,192.168.100.52)の計3台構成でセットアップしました。 ### Controlplaneノードのセットアップ まずはControlplaneノードにK3sをインストールします。192.168.11.50のサーバー上で ```bash curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.34.2+k3s1 \ K3S_TOKEN=CHANGEME \ sh -s - server \ --node-ip=192.168.100.50 \ --node-name=192.168.100.50 \ --advertise-address=192.168.100.50 \ --disable=traefik \ --disable=local-storage ``` 状態を確認します。 ```bash $ sudo systemctl status k3s | cat ● k3s.service - Lightweight Kubernetes Loaded: loaded (/etc/systemd/system/k3s.service; enabled; preset: enabled) Active: active (running) since Thu 2025-11-27 14:05:52 UTC; 10s ago Docs: https://k3s.io Process: 1036001 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0/SUCCESS) Process: 1036002 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS) Main PID: 1036004 (k3s-server) Tasks: 48 Memory: 540.8M (peak: 550.0M) CPU: 15.836s CGroup: /system.slice/k3s.service ├─1036004 "/usr/local/bin/k3s server" ├─1036025 "containerd " ├─1036367 /var/lib/rancher/k3s/data/96d729345c5cd40a1f306326c270ddd621a6acdf003606e91630f8c8147ba6ac/bin/containerd-shim-runc-v2 -namespace k8s.io -id ae731258755b088fe830f46096c8651229a363412a8ad972d4053c1fdc067761 -address /run/k3s/containerd/containerd.sock └─1036373 /var/lib/rancher/k3s/data/96d729345c5cd40a1f306326c270ddd621a6acdf003606e91630f8c8147ba6ac/bin/containerd-shim-runc-v2 -namespace k8s.io -id 15269957327d39ec3f431b632afdc71ecee76e185ad672ab204501e37e59e632 -address /run/k3s/containerd/containerd.sock Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Started tunnel to 192.168.100.50:6443" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Connecting to proxy" url="wss://192.168.100.50:6443/v1-k3s/connect" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Stopped tunnel to 127.0.0.1:6443" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Proxy done" err="context canceled" url="wss://127.0.0.1:6443/v1-k3s/connect" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="error in remotedialer server [400]: websocket: close 1006 (abnormal closure): unexpected EOF" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Handling backend connection request [192.168.100.50]" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Connected to proxy" url="wss://192.168.100.50:6443/v1-k3s/connect" Nov 27 14:05:59 apricot k3s[1036004]: time="2025-11-27T14:05:59Z" level=info msg="Remotedialer connected to proxy" url="wss://192.168.100.50:6443/v1-k3s/connect" Nov 27 14:06:02 apricot k3s[1036004]: I1127 14:06:02.892827 1036004 kuberuntime_manager.go:1828] "Updating runtime config through cri with podcidr" CIDR="10.42.0.0/24" Nov 27 14:06:02 apricot k3s[1036004]: I1127 14:06:02.894417 1036004 kubelet_network.go:47] "Updating Pod CIDR" originalPodCIDR="" newPodCIDR="10.42.0.0/24" ``` kubeconfigをコピーします。 ```bash sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config sudo chown $USER:$USER ~/.kube/config chmod 600 ~/.kube/config ``` NodeとPodの状態を確認します。 ```bash $ kubectl get node,pod -owide -A NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node/192.168.100.50 Ready control-plane 35s v1.34.2+k3s1 192.168.100.50 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system pod/coredns-7f496c8d7d-q2qw6 1/1 Running 0 29s 10.42.0.3 192.168.100.50 kube-system pod/metrics-server-7b9c9c4b9c-xwq2r 1/1 Running 0 29s 10.42.0.2 192.168.100.50 ``` ### Workerノードのセットアップ Worker 1台目 (192.168.11.51)をセットアップします。192.168.11.51のサーバー上で次を実行します。 ```bash curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.34.2+k3s1 \ K3S_URL=https://192.168.100.50:6443 \ K3S_TOKEN=CHANGEME \ sh -s - agent \ --node-ip=192.168.100.51 \ --node-name=192.168.100.51 ``` Controlplane(192.168.11.50)のサーバー上でNodeとPodの状態を確認します。 ```bash $ kubectl get node,pod -owide -A NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node/192.168.100.50 Ready control-plane 85s v1.34.2+k3s1 192.168.100.50 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 node/192.168.100.51 Ready 8s v1.34.2+k3s1 192.168.100.51 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system pod/coredns-7f496c8d7d-q2qw6 1/1 Running 0 79s 10.42.0.3 192.168.100.50 kube-system pod/metrics-server-7b9c9c4b9c-xwq2r 1/1 Running 0 79s 10.42.0.2 192.168.100.50 ``` Worker 2台目 (192.168.11.52)をセットアップします。192.168.11.52のサーバー上で次を実行します。 ```bash curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.34.2+k3s1 \ K3S_URL=https://192.168.100.50:6443 \ K3S_TOKEN=CHANGEME \ sh -s - agent \ --node-ip=192.168.100.52 \ --node-name=192.168.100.52 ``` Controlplane(192.168.11.50)のサーバー上でNodeとPodの状態を確認します。 ```bash $ kubectl get node,pod -owide -A NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME node/192.168.100.50 Ready control-plane 2m10s v1.34.2+k3s1 192.168.100.50 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 node/192.168.100.51 Ready 53s v1.34.2+k3s1 192.168.100.51 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 node/192.168.100.52 Ready 9s v1.34.2+k3s1 192.168.100.52 Ubuntu 24.04.2 LTS 6.8.0-87-generic containerd://2.1.5-k3s1 NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES kube-system pod/coredns-7f496c8d7d-q2qw6 1/1 Running 0 2m4s 10.42.0.3 192.168.100.50 kube-system pod/metrics-server-7b9c9c4b9c-xwq2r 1/1 Running 0 2m4s 10.42.0.2 192.168.100.50 ``` ### Synology CSI Driverのインストール 次に[Synology CSI Driver](https://github.com/SynologyOpenSource/synology-csi)をインストールします。次のようにマニフェストを用意します。 ```bash git clone https://github.com/SynologyOpenSource/synology-csi.git -b v1.2.1 cd synology-csi cp config/client-info-template.yml config/client-info.yml vim config/client-info.yml ``` `client-info.yml`にSynology NASの情報を設定します。 Storage Classの設定ファイルを編集します。 ```bash vim deploy/kubernetes/v1.20/storage-class.yml ``` 次の設定にします。 ```yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: synology-iscsi-storage annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: csi.san.synology.com parameters: fsType: 'btrfs' dsm: '192.168.100.200' location: '/volume1' formatOptions: '--nodiscard' reclaimPolicy: Delete allowVolumeExpansion: true ``` 次のコマンドでSynology CSI Driverをインストールします。 ```bash ./scripts/deploy.sh install --basic ``` 次のような出力が得られます。 ``` ==== Creates namespace and secrets, then installs synology-csi ==== Current Server Version: v1.34.2+k3s1 Deploy Version: v1.20 namespace/synology-csi created secret/client-info-secret created serviceaccount/csi-controller-sa created clusterrole.rbac.authorization.k8s.io/synology-csi-controller-role created clusterrolebinding.rbac.authorization.k8s.io/synology-csi-controller-role created statefulset.apps/synology-csi-controller created csidriver.storage.k8s.io/csi.san.synology.com created namespace/synology-csi unchanged serviceaccount/csi-node-sa created clusterrole.rbac.authorization.k8s.io/synology-csi-node-role created clusterrolebinding.rbac.authorization.k8s.io/synology-csi-node-role created daemonset.apps/synology-csi-node created storageclass.storage.k8s.io/synology-iscsi-storage created ``` `synology-csi` NamespaceのPodの状態を確認します。 ```bash $ kubectl get pod -owide -n synology-csi NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES synology-csi-controller-0 4/4 Running 0 116s 192.168.100.52 192.168.100.52 synology-csi-node-bhcpf 2/2 Running 0 115s 192.168.100.50 192.168.100.50 synology-csi-node-p6mq8 2/2 Running 0 115s 192.168.100.52 192.168.100.52 synology-csi-node-tz6hl 2/2 Running 0 115s 192.168.100.51 192.168.100.51 ``` ### Persistent Volumeの動作確認 次のPVCを作成して、動作を確認します。 ```yaml cat < /tmp/pvc.yaml --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-dynamic-volume-claim spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: synology-iscsi-storage --- EOF kubectl apply -f /tmp/pvc.yaml ``` 次のようにPVCが`Bound`状態になれば成功です。 ```bash $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE test-dynamic-volume-claim Bound pvc-6df54034-c251-4184-9d58-cf7b2fa1c039 1Gi RWO synology-iscsi-storage 7s ``` Synology NAS側のSAN ManagerでLUNとiSCSI Targetも作成されていることを確認できます。 ![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1852/0ea705a6-1cb9-41fa-9173-8831b15956ca.png) ![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1852/2faeac88-2404-41d3-925b-94ddc8d74747.png) このPVCをマウントするPodを作成し、読み書きの動作確認を行います。 ```yaml cat < /tmp/pvc-test-pod.yaml --- apiVersion: v1 kind: Pod metadata: name: pvc-test-pod spec: securityContext: runAsUser: 1000 runAsGroup: 100 fsGroup: 100 containers: - name: test-container image: busybox:latest command: ["/bin/sh"] args: - -c - | echo "=== PVC Read/Write Test Start ===" echo "Mount point check:" df -h /mnt/test echo "" echo "=== Write Test ===" echo "Hello from PVC test - $(date)" >> /mnt/test/test-file.txt echo "File write completed" echo "" echo "=== File Verification ===" ls -lah /mnt/test/ echo "" echo "=== Read Test ===" cat /mnt/test/test-file.txt echo "" echo "=== Test Completed ===" sleep infinity volumeMounts: - name: test-volume mountPath: /mnt/test volumes: - name: test-volume persistentVolumeClaim: claimName: test-dynamic-volume-claim restartPolicy: Never --- EOF kubectl apply -f /tmp/pvc-test-pod.yaml ``` 次のようにPodがReadyになれば成功です。 ```bash $ kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pvc-test-pod 1/1 Running 0 24s 10.42.1.4 192.168.100.51 ``` ログを確認し、読み書きができていることを確認します。 ```bash $ kubectl logs pvc-test-pod === PVC Read/Write Test Start === Mount point check: Filesystem Size Used Available Use% Mounted on /dev/sdd 1.0G 5.8M 904.6M 1% /mnt/test === Write Test === File write completed === File Verification === total 24K drwxrwsr-x 1 root users 26 Nov 27 14:22 . drwxr-xr-x 3 root root 4.0K Nov 27 14:22 .. -rw-r--r-- 1 1000 users 51 Nov 27 14:22 test-file.txt === Read Test === Hello from PVC test - Thu Nov 27 14:16:50 UTC 2025 === Test Completed === ``` 次のコマンドでPodを再作成し、データが保持されていることを確認します。 ```bash kubectl delete pod pvc-test-pod --force kubectl apply -f /tmp/pvc-test-pod.yaml ``` ログを確認し、ファイルに行が追記されていることを確認します。 ```bash $ kubectl logs pvc-test-pod === PVC Read/Write Test Start === Mount point check: Filesystem Size Used Available Use% Mounted on /dev/sdd 1.0G 5.8M 904.6M 1% /mnt/test === Write Test === File write completed === File Verification === total 24K drwxrwsr-x 1 root users 26 Nov 27 14:22 . drwxr-xr-x 3 root root 4.0K Nov 27 14:23 .. -rw-rw-r-- 1 1000 users 102 Nov 27 14:23 test-file.txt === Read Test === Hello from PVC test - Thu Nov 27 14:16:50 UTC 2025 Hello from PVC test - Thu Nov 27 14:16:50 UTC 2025 === Test Completed === ``` 次のコマンドでPodとPVCを削除します。 ```bash kubectl delete pod pvc-test-pod --force kubectl delete pvc test-dynamic-volume-claim ``` SAN ManagerでLUNとiSCSI Targetも削除されていることを確認できます。 ### HelmでRedisをインストールして動作確認 次にHelmを使ってRedisをインストールし、動作確認を行います。 ```bash helm upgrade --install redis \ oci://registry-1.docker.io/bitnamicharts/redis \ -n redis \ --create-namespace --wait \ --set auth.enabled=false ``` 次のようにPodとPVCが作成されていることを確認します。 ```bash $ kubectl get pod,pvc -owide -n redis NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pod/redis-master-0 1/1 Running 0 2m36s 10.42.1.11 192.168.100.51 pod/redis-replicas-0 1/1 Running 0 2m36s 10.42.1.12 192.168.100.51 pod/redis-replicas-1 1/1 Running 0 114s 10.42.2.5 192.168.100.52 pod/redis-replicas-2 1/1 Running 0 72s 10.42.0.4 192.168.100.50 NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE VOLUMEMODE persistentvolumeclaim/redis-data-redis-master-0 Bound pvc-5f7792b3-3c49-44d6-8167-0ebc4f4e66fb 8Gi RWO synology-iscsi-storage 2m36s Filesystem persistentvolumeclaim/redis-data-redis-replicas-0 Bound pvc-ea541f4a-879a-4ccd-9654-49efc018d87d 8Gi RWO synology-iscsi-storage 2m36s Filesystem persistentvolumeclaim/redis-data-redis-replicas-1 Bound pvc-80964ce4-bb0d-4d2d-8b19-881feb82a6ed 8Gi RWO synology-iscsi-storage 115s Filesystem persistentvolumeclaim/redis-data-redis-replicas-2 Bound pvc-02e1e1dc-0646-447c-89d5-6f16215d27cf 8Gi RWO synology-iscsi-storage 72s Filesystem ``` 次のコマンドでRedisマスターにポートフォワードし、`redis-cli`で接続して動作確認を行います。 ```bash kubectl port-forward --namespace redis svc/redis-master 6379:6379 ``` 次のようにRedisに接続して、データの読み書きができることを確認します。 ```bash $ redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379> set foo 100 OK 127.0.0.1:6379> get foo "100" ``` 次のコマンドでRedisをアンインストールし、PVCも削除します。 ```bash helm uninstall -n redis redis --wait kubectl delete pvc -n redis --all kubectl delete ns redis ``` --- K3sにSynology CSI Driverをインストールして、Synology NASのiSCSI LUNをKubernetesのPersistent Volumeとして利用することができました。 K3sは軽量でセットアップも簡単なので、自宅サーバーでKubernetesクラスターを構築するのに便利です。