[{"content":"Installing Synology CSI Operator Installing Synology CSI Operator Exploration Solution Synology Operator Installation Testing the Installation Next Steps Backups Cloud Native PostgreSQL Operator Integration FluxCD Integration Exploration Spinning up and tearing down short-lived ephemeral deployments in my self-hosted kubernetes homelab has been a fun learning experience, but as I want to make some deployments more persistent, I need a way to provision long-lived storage.\nA key requirement is that if node02 goes down and a pod is re-scheduled to a different node, the data stored needs to persist somewhere accessible by the other nodes.\nSolution I picked up a DS118 with a 2TB WD Red from eBay for a decent price.\nThere is a Synology Kubernetes Operator that can manage the provisioning of volumes for use by Kubernetes.\nThe repo contains a very good installation guide.\nThis solution meets all my requirements, providing some redundancy to my apps.\nSynology Operator Installation The full installation of the operator is very simple:\nEnsure the Synology has at least one volume created\nClone the synology-csi repo\nCopy config/client-info-template.yml to config/client-info.yml and fill out the Synology details:\nclients: - host: \u0026lt;synology-ip\u0026gt; port: 5000 https: false username: \u0026lt;synology-user\u0026gt; password: \u0026lt;synology-password\u0026gt; Configure some storage classes in deploy/kubernetes/v1.20: # storage-class.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: synology-iscsi annotations: storageclass.kubernetes.io/is-default-class: \u0026#34;true\u0026#34; provisioner: csi.san.synology.com parameters: dsm: \u0026lt;synology-ip\u0026gt; location: \u0026#34;/volume1\u0026#34; protocol: iscsi fsType: ext4 reclaimPolicy: Delete allowVolumeExpansion: true --- # storage-class-retain.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: synology-iscsi-retain annotations: provisioner: csi.san.synology.com parameters: dsm: \u0026lt;synology-ip\u0026gt; location: \u0026#34;/volume1\u0026#34; protocol: iscsi fsType: ext4 reclaimPolicy: Retain allowVolumeExpansion: true The default storage class will work out of the box, but remember it does not set the new Synology storage class as the default class to be used by the provisioner for any new volumes.\nRun the install script: ./scripts/deploy.sh run Verify everything installed okay: (ins)❯ k get all -n synology-csi NAME READY STATUS RESTARTS AGE pod/synology-csi-controller-0 4/4 Running 0 14h pod/synology-csi-node-bhnzq 2/2 Running 0 14h pod/synology-csi-node-bw2j7 2/2 Running 0 14h pod/synology-csi-node-g9dfv 2/2 Running 0 14h pod/synology-csi-node-j778m 2/2 Running 0 14h pod/synology-csi-snapshotter-0 2/2 Running 0 14h NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE daemonset.apps/synology-csi-node 4 4 4 4 4 \u0026lt;none\u0026gt; 14h NAME READY AGE statefulset.apps/synology-csi-controller 1/1 14h statefulset.apps/synology-csi-snapshotter 1/1 14h ~ (ins)❯ k get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 32d synology-iscsi (default) csi.san.synology.com Delete Immediate true 13h synology-iscsi-retain csi.san.synology.com Retain Immediate true 13h ~ (ins)❯ k get secrets -n synology-csi NAME TYPE DATA AGE client-info-secret Opaque 1 14h Looking good!\nTesting the Installation I used the following nginx deployment and pvc to test mounting a 1Gi volume provisioned by the operator:\n# synology-test.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: synology-test-pvc namespace: default labels: app: synology-test-pvc spec: storageClassName: synology-iscsi accessModes: - ReadWriteOnce resources: requests: storage: 1Gi --- apiVersion: apps/v1 kind: Deployment metadata: name: synology-test namespace: default spec: replicas: 1 selector: matchLabels: app: synology-test template: metadata: labels: app: synology-test spec: containers: - name: nginx image: nginx volumeMounts: - name: data mountPath: /usr/share/nginx/html volumes: - name: data persistentVolumeClaim: claimName: synology-test-pvc Provisioned pvc:\n(ins)❯ k get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE synology-test-pvc Bound pvc-75fa9690-5bf3-4ceb-ac01-ebc13be44ff8 1Gi RWO synology-iscsi \u0026lt;unset\u0026gt; 50m On the Synology UI:\nNext Steps Backups The end-goal for backups is to remain outside of Synology DSM.\nAs most of the apps I will use and create will have cnpg databases, the plan is to point the backup and seed properties of cnpg clusters to Azure blob storage.\nCloud Native PostgreSQL Operator Integration The next step for spinning up persistent deployments and creating cloud-native dotnet apps is creating postgresql databases with the Synology as the backing storage.\nI will need to explore if the default storage class annotation is enough for any new cnpg cluster to use Synology operator volumes automatically.\nFluxCD Integration I chose not to bring synology-csi into flux just yet, as it is one of those deployments I would prefer manual control over due to its non-idempotent nature.\nI have still defined the kustomization.yaml in case I decide to GitOps the Synology in the future.\n","permalink":"http://blog.bde-dev.net/posts/synology-csi-operator/","summary":"\u003ch1 id=\"installing-synology-csi-operator\"\u003eInstalling Synology CSI Operator\u003c/h1\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#installing-synology-csi-operator\"\u003eInstalling Synology CSI Operator\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#exploration\"\u003eExploration\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#solution\"\u003eSolution\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#synology-operator-installation\"\u003eSynology Operator Installation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#testing-the-installation\"\u003eTesting the Installation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#next-steps\"\u003eNext Steps\u003c/a\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"#backups\"\u003eBackups\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#cloud-native-postgresql-operator-integration\"\u003eCloud Native PostgreSQL Operator Integration\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#fluxcd-integration\"\u003eFluxCD Integration\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003ch2 id=\"exploration\"\u003eExploration\u003c/h2\u003e\n\u003cp\u003eSpinning up and tearing down short-lived ephemeral deployments in my self-hosted \u003ccode\u003ekubernetes\u003c/code\u003e \u003ca href=\"https://github.com/bde-dev/homelab\"\u003ehomelab\u003c/a\u003e has been a fun learning experience, but as I want to make some deployments more persistent, I need a way to provision long-lived storage.\u003c/p\u003e","title":"synology csi operator"},{"content":"homelab init Finally got round to initializing my homelab!\nIt is a 4-node cluster, consisting of 1 control plane and 3 workers.\nChosen Hardware All 4 nodes are HP EliteDesk 800 G2 Mini PC\u0026rsquo;s.\nPicked them up really cheap from eBay.\nChosen Software I opted for ubuntu-server-24.04 LTS running k3s.\nThe initial OS choice was easy as I have a few years experience with ubuntu server at my current employer.\nI have installed a few minimal playground k3s clusters before on ubuntu-server VM\u0026rsquo;s, so again I thought I would stick to what I know and use k3s.\nInstallation I used k3s-ansible to bootstrap the cluster.\nThere are many community playbooks for installing a k3s cluster, but I generally prefer getting as close to the maintainers of the parent tool (i.e k3s-io) as I can.\nIt is likely k3s-io will reliably maintain their own playbook, rather than relying on a community maintained playbook.\nI opted for the repository installation rather than through ansible-galaxy as to not add a dependency tied to my host ansible-controller. Should the need arise, I can keep my inventory-sample.yaml in source control and simply re-bootstrap using the same method.\nIf I find myself having to re-bootstrap often, I may bring in k3s-ansible as a git submodule.\nAs this is just the initial bootstrap, these are the only things that changed in my inventory-sample.yaml:\nhosts - set to the IP addresses of my nodes ansible_user - changed from debian to the primary user on my nodes k3s_version - I set this to the latest release at the time of installation v1.33.1+k3s1 ansible_become_pass - To handle passwordless SSH access from my ansible-ontroller to the nodes, I used ssh-copy-id and this ansible_become_pass token - Not using Vagrant so commented this var out cluster_context - set the name of the context to homelab Next Steps I have big plans for this cluster, including devpods, deploying common self-hosted apps such as linkding and commafeed, and to create an environment that allows me to deploy my own .NET apps and expose them securely to the internet.\nMore details on these milestones can be found in the repo README.md.\nI will be posting here at every milestone, and granular progress can be followed in the repo - homelab.\n","permalink":"http://blog.bde-dev.net/posts/homelab-init/","summary":"\u003ch1 id=\"homelab-init\"\u003e\u003ccode\u003ehomelab init\u003c/code\u003e\u003c/h1\u003e\n\u003cp\u003eFinally got round to initializing my homelab!\u003c/p\u003e\n\u003cp\u003eIt is a 4-node cluster, consisting of 1 control plane and 3 workers.\u003c/p\u003e\n\u003ch2 id=\"chosen-hardware\"\u003eChosen Hardware\u003c/h2\u003e\n\u003cp\u003eAll 4 nodes are HP EliteDesk 800 G2 Mini PC\u0026rsquo;s.\u003c/p\u003e\n\u003cp\u003ePicked them up really cheap from eBay.\u003c/p\u003e\n\u003ch2 id=\"chosen-software\"\u003eChosen Software\u003c/h2\u003e\n\u003cp\u003eI opted for \u003ccode\u003eubuntu-server-24.04 LTS\u003c/code\u003e running \u003ccode\u003ek3s\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eThe initial OS choice was easy as I have a few years experience with \u003ccode\u003eubuntu server\u003c/code\u003e at my current employer.\u003c/p\u003e","title":"homelab init"},{"content":"blog init Hi there, I\u0026rsquo;m Brad.\nI am a command line inhabitant passionate about software delivery correctness, efficiency and automation, system and app architecture, all in the context of cloud tech and Kubernetes.\nI plan to use this blog to write about my labs, things that interest me, challenge me, or unique projects where Google didn\u0026rsquo;t help much.\nExpect to see posts about Kubernetes, .NET, Azure, Unity, vim, Linux and perhaps some gaming bits.\n","permalink":"http://blog.bde-dev.net/posts/blog-init/","summary":"\u003ch1 id=\"blog-init\"\u003e\u003ccode\u003eblog init\u003c/code\u003e\u003c/h1\u003e\n\u003cp\u003eHi there, I\u0026rsquo;m Brad.\u003c/p\u003e\n\u003cp\u003eI am a command line inhabitant passionate about software delivery correctness, efficiency and automation, system and app architecture, all in the context of cloud tech and Kubernetes.\u003c/p\u003e\n\u003cp\u003eI plan to use this blog to write about my labs, things that interest me, challenge me, or unique projects where Google didn\u0026rsquo;t help much.\u003c/p\u003e\n\u003cp\u003eExpect to see posts about Kubernetes, .NET, Azure, Unity, vim, Linux and perhaps some gaming bits.\u003c/p\u003e","title":"blog init"},{"content":"","permalink":"http://blog.bde-dev.net/blog/","summary":"","title":"Blog"},{"content":"","permalink":"http://blog.bde-dev.net/about/","summary":"","title":"About"}]