From 31bf8326887f857f528d294ef99906c91b62c2bc Mon Sep 17 00:00:00 2001 From: ytimocin Date: Tue, 27 Jan 2026 09:13:09 -0800 Subject: [PATCH] feat: shared PVC for Terraform storage across applications-rp and dynamic-rp Signed-off-by: ytimocin --- .../actions/create-kind-cluster/action.yaml | 15 +++++ .github/workflows/functional-test-cloud.yaml | 12 ++++ .../templates/dynamic-rp/deployment.yaml | 9 ++- deploy/Chart/templates/rp/deployment.yaml | 9 ++- deploy/Chart/templates/terraform-pvc.yaml | 19 ++++++ deploy/Chart/tests/terraform_test.yaml | 62 ++++++++++++++++--- pkg/terraform/installer/handler.go | 2 +- 7 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 deploy/Chart/templates/terraform-pvc.yaml diff --git a/.github/actions/create-kind-cluster/action.yaml b/.github/actions/create-kind-cluster/action.yaml index 530ba02f05..bfc4152f0d 100644 --- a/.github/actions/create-kind-cluster/action.yaml +++ b/.github/actions/create-kind-cluster/action.yaml @@ -169,3 +169,18 @@ runs: host: "${{ inputs.registry-name }}:${{ inputs.registry-port }}" help: "https://kind.sigs.k8s.io/docs/user/local-registry/" EOF + + - name: Install NFS provisioner for ReadWriteMany PVC support + shell: bash + run: | + # Add NFS provisioner Helm repo (suppress "already exists" errors, but update regardless) + helm repo add nfs-ganesha-server-and-external-provisioner \ + https://kubernetes-sigs.github.io/nfs-ganesha-server-and-external-provisioner/ 2>/dev/null || true + helm repo update nfs-ganesha-server-and-external-provisioner + + # Install NFS provisioner with RWX support as default storage class + helm install nfs-server nfs-ganesha-server-and-external-provisioner/nfs-server-provisioner \ + --set persistence.enabled=false \ + --set storageClass.name=nfs \ + --set storageClass.defaultClass=true \ + --wait --timeout 5m diff --git a/.github/workflows/functional-test-cloud.yaml b/.github/workflows/functional-test-cloud.yaml index 8e1a9b0b24..77f82f3d7d 100644 --- a/.github/workflows/functional-test-cloud.yaml +++ b/.github/workflows/functional-test-cloud.yaml @@ -675,6 +675,18 @@ jobs: service-account-private-key-file: /etc/kubernetes/pki/sa.key EOF + - name: Install NFS provisioner for ReadWriteMany PVC support + run: | + helm repo add nfs-ganesha-server-and-external-provisioner \ + https://kubernetes-sigs.github.io/nfs-ganesha-server-and-external-provisioner/ 2>/dev/null || true + helm repo update nfs-ganesha-server-and-external-provisioner + + helm install nfs-server nfs-ganesha-server-and-external-provisioner/nfs-server-provisioner \ + --set persistence.enabled=false \ + --set storageClass.name=nfs \ + --set storageClass.defaultClass=true \ + --wait --timeout 5m + - name: Install Azure Keyvault CSI driver chart run: | helm repo add csi-secrets-store-provider-azure https://azure.github.io/secrets-store-csi-driver-provider-azure/charts diff --git a/deploy/Chart/templates/dynamic-rp/deployment.yaml b/deploy/Chart/templates/dynamic-rp/deployment.yaml index 3b7d0b9d8a..b554f1f7a5 100644 --- a/deploy/Chart/templates/dynamic-rp/deployment.yaml +++ b/deploy/Chart/templates/dynamic-rp/deployment.yaml @@ -124,8 +124,10 @@ spec: echo "Terraform binary successfully pre-downloaded and installed" volumeMounts: + {{- if eq .Values.global.terraform.enabled true }} - name: terraform mountPath: {{ .Values.dynamicrp.terraform.path }} + {{- end }} securityContext: allowPrivilegeEscalation: false runAsNonRoot: true @@ -167,8 +169,10 @@ spec: - name: aws-iam-token mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount {{- end }} + {{- if eq .Values.global.terraform.enabled true }} - name: terraform mountPath: {{ .Values.dynamicrp.terraform.path }} + {{- end }} - name: encryption-secret mountPath: /var/secrets/encryption readOnly: true @@ -198,8 +202,11 @@ spec: expirationSeconds: 86400 audience: "sts.amazonaws.com" {{- end }} + {{- if eq .Values.global.terraform.enabled true }} - name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage + {{- end }} - name: encryption-secret secret: secretName: radius-encryption-key diff --git a/deploy/Chart/templates/rp/deployment.yaml b/deploy/Chart/templates/rp/deployment.yaml index b03f6d91f4..a2be184bb4 100644 --- a/deploy/Chart/templates/rp/deployment.yaml +++ b/deploy/Chart/templates/rp/deployment.yaml @@ -130,8 +130,10 @@ spec: echo "Terraform binary successfully pre-downloaded and installed" volumeMounts: + {{- if eq .Values.global.terraform.enabled true }} - name: terraform mountPath: {{ .Values.rp.terraform.path }} + {{- end }} securityContext: allowPrivilegeEscalation: false runAsNonRoot: true @@ -180,8 +182,10 @@ spec: - name: aws-iam-token mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount {{- end }} + {{- if eq .Values.global.terraform.enabled true }} - name: terraform mountPath: {{ .Values.rp.terraform.path }} + {{- end }} {{- if .Values.global.rootCA.cert }} - name: {{ .Values.global.rootCA.volumeName }} mountPath: {{ .Values.global.rootCA.mountPath }} @@ -208,8 +212,11 @@ spec: expirationSeconds: 86400 audience: "sts.amazonaws.com" {{- end }} + {{- if eq .Values.global.terraform.enabled true }} - name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage + {{- end }} {{- if .Values.global.rootCA.cert }} - name: {{ .Values.global.rootCA.volumeName }} secret: diff --git a/deploy/Chart/templates/terraform-pvc.yaml b/deploy/Chart/templates/terraform-pvc.yaml new file mode 100644 index 0000000000..f62ccba441 --- /dev/null +++ b/deploy/Chart/templates/terraform-pvc.yaml @@ -0,0 +1,19 @@ +{{- if .Values.global.terraform.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: terraform-storage + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: terraform-storage + app.kubernetes.io/part-of: radius +spec: + accessModes: + - ReadWriteMany + {{- if .Values.global.terraform.storageClassName }} + storageClassName: {{ .Values.global.terraform.storageClassName | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.global.terraform.storageSize | default "1Gi" }} +{{- end }} diff --git a/deploy/Chart/tests/terraform_test.yaml b/deploy/Chart/tests/terraform_test.yaml index eee59898d7..ba8b75aa46 100644 --- a/deploy/Chart/tests/terraform_test.yaml +++ b/deploy/Chart/tests/terraform_test.yaml @@ -3,9 +3,47 @@ templates: - rp/deployment.yaml - rp/configmaps.yaml - dynamic-rp/deployment.yaml + - terraform-pvc.yaml tests: + # Terraform PVC tests + - it: should create terraform PVC when terraform is enabled + set: + global.terraform.enabled: true + asserts: + - isKind: + of: PersistentVolumeClaim + template: terraform-pvc.yaml + - equal: + path: metadata.name + value: terraform-storage + template: terraform-pvc.yaml + - contains: + path: spec.accessModes + content: ReadWriteMany + template: terraform-pvc.yaml + + - it: should use custom storage class when specified + set: + global.terraform.enabled: true + global.terraform.storageClassName: "nfs" + asserts: + - equal: + path: spec.storageClassName + value: "nfs" + template: terraform-pvc.yaml + + - it: should use custom storage size when specified + set: + global.terraform.enabled: true + global.terraform.storageSize: "5Gi" + asserts: + - equal: + path: spec.resources.requests.storage + value: "5Gi" + template: terraform-pvc.yaml + # applications-rp terraform volume tests - - it: should create emptyDir terraform volume in applications-rp when terraform is enabled + - it: should use PVC for terraform volume in applications-rp when terraform is enabled set: global.terraform.enabled: true rp.image: applications-rp @@ -15,7 +53,8 @@ tests: path: spec.template.spec.volumes content: name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage template: rp/deployment.yaml - it: should mount terraform volume in applications-rp container @@ -56,7 +95,7 @@ tests: template: rp/configmaps.yaml # dynamic-rp terraform volume tests - - it: should create emptyDir terraform volume in dynamic-rp when terraform is enabled + - it: should use PVC for terraform volume in dynamic-rp when terraform is enabled set: global.terraform.enabled: true dynamicrp.image: dynamic-rp @@ -66,7 +105,8 @@ tests: path: spec.template.spec.volumes content: name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage template: dynamic-rp/deployment.yaml - it: should mount terraform volume in dynamic-rp container @@ -99,8 +139,8 @@ tests: any: true template: dynamic-rp/deployment.yaml - # Both deployments use independent emptyDir volumes (pod-local storage) - - it: should use independent emptyDir volumes for each deployment + # Both deployments use the same shared PVC + - it: should use shared PVC for both deployments set: global.terraform.enabled: true rp.image: applications-rp @@ -108,17 +148,19 @@ tests: dynamicrp.image: dynamic-rp dynamicrp.tag: latest asserts: - # applications-rp uses emptyDir + # applications-rp uses shared PVC - contains: path: spec.template.spec.volumes content: name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage template: rp/deployment.yaml - # dynamic-rp uses emptyDir + # dynamic-rp uses same shared PVC - contains: path: spec.template.spec.volumes content: name: terraform - emptyDir: {} + persistentVolumeClaim: + claimName: terraform-storage template: dynamic-rp/deployment.yaml diff --git a/pkg/terraform/installer/handler.go b/pkg/terraform/installer/handler.go index 0a2885797b..a901cdb54f 100644 --- a/pkg/terraform/installer/handler.go +++ b/pkg/terraform/installer/handler.go @@ -404,7 +404,7 @@ func (h *Handler) download(ctx context.Context, opts *downloadOptions) error { } client = tlsClient } else { - client = http.DefaultClient + client = &http.Client{Timeout: DefaultDownloadTimeout} } }