{"id":18262214,"url":"https://github.com/inveniem/kustomize-storage-config-transformer","last_synced_at":"2026-04-30T15:31:31.559Z","repository":{"id":130335522,"uuid":"445396125","full_name":"Inveniem/kustomize-storage-config-transformer","owner":"Inveniem","description":"Kustomize KRM function/generator for adding persistent volumes (PV), persistent volume claims (PVC), and volume mounts to Kubernetes deployment manifests from dynamic data.","archived":false,"fork":false,"pushed_at":"2023-02-12T04:26:17.000Z","size":73,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-09T00:48:30.600Z","etag":null,"topics":["kubernetes","kustomize-plugin"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Inveniem.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-07T04:22:10.000Z","updated_at":"2023-10-05T14:57:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"e456ba69-eec8-4322-9f62-c4e7c62d6081","html_url":"https://github.com/Inveniem/kustomize-storage-config-transformer","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/Inveniem/kustomize-storage-config-transformer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inveniem%2Fkustomize-storage-config-transformer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inveniem%2Fkustomize-storage-config-transformer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inveniem%2Fkustomize-storage-config-transformer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inveniem%2Fkustomize-storage-config-transformer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Inveniem","download_url":"https://codeload.github.com/Inveniem/kustomize-storage-config-transformer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Inveniem%2Fkustomize-storage-config-transformer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32469344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"ssl_error","status_checked_at":"2026-04-30T13:12:06.837Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","kustomize-plugin"],"created_at":"2024-11-05T11:07:02.567Z","updated_at":"2026-04-30T15:31:31.541Z","avatar_url":"https://github.com/Inveniem.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kustomize Storage Config Transformer\nAs a DevOps professional who is hosting the same containerized software for\nmultiple tenants on the same Kubernetes infrastructure and who needs to keep the\ndata for each client in a separate volume (potentially even in different storage\naccounts like Azure Files, Azure Blob, S3, Qumulo, etc.), the Kustomize Storage\nConfig Transformer is a KRM function that can take in a list of tenant names and\ntransform them into deployment manifests that contain appropriate declarations\nof Persistent Volumes (PVs), Persistent Volume Claims (PVCs), volume mounts, and\ncontainer mounts.\n\nFor example, consider the following base deployment manifest:\n```yaml\n# base/deployment.yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: myapp-api\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n      app: backend-myapp-api\n  template:\n    metadata:\n      labels:\n        app: backend-myapp-api\n        role: backend\n    spec:\n      containers:\n        - name: backend-myapp-api\n          image: \"inveniem/myapp-api:latest\"\n          ports:\n            - containerPort: 5000\n        - name: some-other-app1\n          image: \"inveniem/some-other-app1:latest\"\n          ports:\n            - containerPort: 5000\n\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: frontend-myapp\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: frontend-myapp\n  template:\n    metadata:\n      labels:\n        app: frontend-myapp\n        role: frontend\n    spec:\n      containers:\n        - name: frontend-myapp\n          image: \"inveniem/frontend-myapp:latest\"\n          ports:\n            - containerPort: 5000\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: some-other-app2\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: some-other-app2\n  template:\n    metadata:\n      labels:\n        app: some-other-app2\n    spec:\n      containers:\n        - name: some-other-app2\n          image: \"inveniem/some-other-app2:latest\"\n          ports:\n            - containerPort: 5000\n```\n\nNow, consider a \"live\" overlay that has a Kustomization config like this:\n```yaml\n# overlays/live/kustomization.yaml\napiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\n\nresources:\n  - ../../base\n\nnamespace: sample\n\ntransformers:\n  - configure-storage.yaml\n```\n\nAnd a KSCT plugin config like this:\n```yaml\n# overlays/live/configure-storage.yaml\napiVersion: kubernetes.inveniem.com/storage-config-transformer/v1alpha\nkind: StorageConfigTransformer\nmetadata:\n  name: storage-config-transformer\n  annotations:\n    config.kubernetes.io/function: |\n      container:\n        image: inveniem/kustomize-storage-transformer:latest\nspec:\n  - permutations:\n      values:\n        - sample-project1\n        - sample-project2\n        - sample-project3\n\n    persistentVolumeTemplate:\n      spec:\n        capacity:\n          storage: 1Ti\n        accessModes:\n          - ReadWriteMany\n        azureFile:\n          secretName: \"myapp-azure-files-creds\"\n          shareName: \"\u003c\u003cINJECTED\u003e\u003e\"\n      name:\n        prefix: \"pv-myapp-live-\"\n        suffix: ~\n      injectedValues:\n        # \"targetField\" is the new name for \"field\" from v1.0.0. Both \"field\"\n        # and \"targetField\" are allowed in v1.1.0+, but \"field\" is deprecated \n        # and \"targetField\" will be supported as the clearer option going\n        # forward.\n        - targetField: \"spec.azureFile.shareName\"\n          prefix: ~\n          suffix: ~\n\n    persistentVolumeClaimTemplate:\n      spec:\n        storageClassName: \"\"\n        accessModes:\n          - ReadWriteMany\n        resources:\n          requests:\n            storage: 1Ti\n        volumeName: \"\u003c\u003cINJECTED\u003e\u003e\"\n      name:\n        prefix: pvc-\n        suffix: ~\n        replacements:\n          - pattern: '/sample\\-/'\n            replacement: ''\n      namespace: sample\n      injectedValues:\n        # \"targetField\" is the new name for \"field\" from v1.0.0. Both \"field\"\n        # and \"targetField\" are allowed in v1.1.0+, but \"field\" is deprecated \n        # and \"targetField\" will be supported as the clearer option going\n        # forward.\n        - targetField: \"spec.volumeName\"\n          prefix: \"pv-myapp-live-\"\n          suffix: ~\n\n    containerVolumeTemplates:\n      - containers:\n          - name: frontend-myapp\n          - name: backend-myapp-api\n\n        volumeTemplates:\n          - mergeSpec:\n              persistentVolumeClaim:\n                claimName: \"\u003c\u003cINJECTED\u003e\u003e\"\n            name:\n              prefix: \"vol-\"\n              suffix: ~\n            injectedValues:\n              # \"targetField\" is the new name for \"field\" from v1.0.0. Both \n              # \"field\" and \"targetField\" are allowed in v1.1.0+, but \n              # \"targetField\" will be supported as the clearer option going \n              # forward.\n              - targetField: \"persistentVolumeClaim.claimName\"\n                prefix: \"pvc-\"\n                suffix: ~\n                replacements:\n                  - pattern: '/sample\\-/'\n                    replacement: ''\n\n        volumeMountTemplates:\n          - mergeSpec:\n              mountPath: \"\u003c\u003cINJECTED\u003e\u003e\"\n            name:\n              prefix: \"vol-\"\n              suffix: ~\n            injectedValues:\n              # \"targetField\" is the new name for \"field\" from v1.0.0. Both \n              # \"field\" and \"targetField\" are allowed in v1.1.0+, but \n              # \"targetField\" will be supported as the clearer option going \n              # forward.\n              - targetField: \"mountPath\"\n                prefix: \"/mnt/share/\"\n                suffix: ~\n                replacements:\n                  - pattern: '/\\-/'\n                    replacement: '/'\n```\n_(Above, there is nothing special about `\u003c\u003cINJECTED\u003e\u003e` as a value; it's just\nbeing used to make it easier to visualize where the injected values will go in\nthe output template. Keys that have that value in this example could actually\nhave been omitted entirely, and the corresponding value would still be created\nand populated by the `injectedValues`.)_\n\nThis would produce the following deployment manifest:\n```yaml\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: pv-myapp-live-sample-project1\nspec:\n  accessModes:\n    - ReadWriteMany\n  azureFile:\n    secretName: myapp-azure-files-creds\n    shareName: sample-project1\n  capacity:\n    storage: 1Ti\n---\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: pv-myapp-live-sample-project2\nspec:\n  accessModes:\n    - ReadWriteMany\n  azureFile:\n    secretName: myapp-azure-files-creds\n    shareName: sample-project2\n  capacity:\n    storage: 1Ti\n---\napiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: pv-myapp-live-sample-project3\nspec:\n  accessModes:\n    - ReadWriteMany\n  azureFile:\n    secretName: myapp-azure-files-creds\n    shareName: sample-project3\n  capacity:\n    storage: 1Ti\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: pvc-project1\n  namespace: sample\nspec:\n  accessModes:\n    - ReadWriteMany\n  resources:\n    requests:\n      storage: 1Ti\n  storageClassName: \"\"\n  volumeName: pv-myapp-live-sample-project1\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: pvc-project2\n  namespace: sample\nspec:\n  accessModes:\n    - ReadWriteMany\n  resources:\n    requests:\n      storage: 1Ti\n  storageClassName: \"\"\n  volumeName: pv-myapp-live-sample-project2\n---\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: pvc-project3\n  namespace: sample\nspec:\n  accessModes:\n    - ReadWriteMany\n  resources:\n    requests:\n      storage: 1Ti\n  storageClassName: \"\"\n  volumeName: pv-myapp-live-sample-project3\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: frontend-myapp\n  namespace: sample\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: frontend-myapp\n  template:\n    metadata:\n      labels:\n        app: frontend-myapp\n        role: frontend\n    spec:\n      containers:\n        - image: inveniem/frontend-myapp:latest\n          name: frontend-myapp\n          ports:\n            - containerPort: 5000\n          volumeMounts:\n            - mountPath: /mnt/share/sample/project1\n              name: vol-sample-project1\n            - mountPath: /mnt/share/sample/project2\n              name: vol-sample-project2\n            - mountPath: /mnt/share/sample/project3\n              name: vol-sample-project3\n      volumes:\n        - name: vol-sample-project1\n          persistentVolumeClaim:\n            claimName: pvc-project1\n        - name: vol-sample-project2\n          persistentVolumeClaim:\n            claimName: pvc-project2\n        - name: vol-sample-project3\n          persistentVolumeClaim:\n            claimName: pvc-project3\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: myapp-api\n  namespace: sample\nspec:\n  replicas: 2\n  selector:\n    matchLabels:\n      app: backend-myapp-api\n  template:\n    metadata:\n      labels:\n        app: backend-myapp-api\n        role: backend\n    spec:\n      containers:\n        - image: inveniem/myapp-api:latest\n          name: backend-myapp-api\n          ports:\n            - containerPort: 5000\n          volumeMounts:\n            - mountPath: /mnt/share/sample/project1\n              name: vol-sample-project1\n            - mountPath: /mnt/share/sample/project2\n              name: vol-sample-project2\n            - mountPath: /mnt/share/sample/project3\n              name: vol-sample-project3\n        - image: inveniem/some-other-app1:latest\n          name: some-other-app1\n          ports:\n            - containerPort: 5000\n      volumes:\n        - name: vol-sample-project1\n          persistentVolumeClaim:\n            claimName: pvc-project1\n        - name: vol-sample-project2\n          persistentVolumeClaim:\n            claimName: pvc-project2\n        - name: vol-sample-project3\n          persistentVolumeClaim:\n            claimName: pvc-project3\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: some-other-app2\n  namespace: sample\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: some-other-app2\n  template:\n    metadata:\n      labels:\n        app: some-other-app2\n    spec:\n      containers:\n        - image: inveniem/some-other-app2:latest\n          name: some-other-app2\n          ports:\n            - containerPort: 5000\n```\n\nNote that the output manifests include the following:\n1. A PV (available cluster-wide) is declared for each permutation value (e.g.,\n   `sample-project1`, `sample-project2`, etc.), with:\n    1. Each name prefixed according to the name prefix template.\n    2. The specification (`spec`) for each PV is copied from the\n       `persistentVolumeTemplate` from the KSCT config.\n    3. The share name is dynamically-injected based on the `injectedValues`\n       settings in the KSCT config.\n\n2. A PVC (declared in the namespace in which the application is being\n   deployed) is declared for each permutation value, with:\n    1. The name of each PVC prefixed according to the name prefix template.\n    2. Each PVC bound to its corresponding PV via a dynamically-injected\n       `volumeName` attribute value.\n\n3. Volumes, declared in each deployment that contains a container that is\n   referenced by the `containerVolumeTemplates.containers` key in the\n   KSCT config, to reference the PVs; with the settings for each one merged-in\n   from the `mergeSpec` key of the volume template of the KSCT config.\n\n4. Volume mounts, declared for each container that matches a name in the\n   `containerVolumeTemplates.containers` key of the KSCT config, with its\n   settings merged-in from the `mergeSpec` key of the volume mount template of\n   the KSCT config.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finveniem%2Fkustomize-storage-config-transformer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finveniem%2Fkustomize-storage-config-transformer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finveniem%2Fkustomize-storage-config-transformer/lists"}