diff --git a/bootstrapper/internal/helm/helm.go b/bootstrapper/internal/helm/helm.go index b04969b74..036d58862 100644 --- a/bootstrapper/internal/helm/helm.go +++ b/bootstrapper/internal/helm/helm.go @@ -99,7 +99,7 @@ func (h *Client) InstallCilium(ctx context.Context, kubectl k8sapi.Client, relea h.Wait = release.Wait switch in.CloudProvider { - case "aws", "azure", "qemu": + case "aws", "azure", "openstack", "qemu": return h.installCiliumGeneric(ctx, release, in.LoadBalancerEndpoint) case "gcp": return h.installCiliumGCP(ctx, kubectl, release, in.NodeName, in.FirstNodePodCIDR, in.SubnetworkPodCIDR, in.LoadBalancerEndpoint) diff --git a/cli/internal/helm/BUILD.bazel b/cli/internal/helm/BUILD.bazel index e66dfd289..06f52a71a 100644 --- a/cli/internal/helm/BUILD.bazel +++ b/cli/internal/helm/BUILD.bazel @@ -313,6 +313,8 @@ go_library( "charts/edgeless/operators/charts/node-maintenance-operator/values.schema.json", "charts/edgeless/operators/charts/node-maintenance-operator/values.yaml", "charts/edgeless/operators/values.yaml", + "charts/edgeless/constellation-services/charts/ccm/templates/openstack-daemonset.yaml", + "charts/edgeless/constellation-services/charts/ccm/templates/openstack-secret.yaml", ], importpath = "github.com/edgelesssys/constellation/v2/cli/internal/helm", visibility = ["//cli:__subpackages__"], diff --git a/cli/internal/helm/charts/edgeless/constellation-services/Chart.yaml b/cli/internal/helm/charts/edgeless/constellation-services/Chart.yaml index 907f6e224..82fb9d441 100644 --- a/cli/internal/helm/charts/edgeless/constellation-services/Chart.yaml +++ b/cli/internal/helm/charts/edgeless/constellation-services/Chart.yaml @@ -7,23 +7,26 @@ dependencies: - name: key-service version: 0.0.0 tags: + - AWS - Azure - GCP - - AWS + - OpenStack - QEMU - name: join-service version: 0.0.0 tags: + - AWS - Azure - GCP - - AWS + - OpenStack - QEMU - name: ccm version: 0.0.0 tags: + - AWS - Azure - GCP - - AWS + - OpenStack - name: cnm version: 0.0.0 tags: @@ -37,16 +40,18 @@ dependencies: - name: verification-service version: 0.0.0 tags: + - AWS - Azure - GCP - - AWS + - OpenStack - QEMU - name: konnectivity version: 0.0.0 tags: + - AWS - Azure - GCP - - AWS + - OpenStack - QEMU - name: gcp-guest-agent version: 0.0.0 diff --git a/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-daemonset.yaml b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-daemonset.yaml new file mode 100644 index 000000000..4b32a4bc9 --- /dev/null +++ b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-daemonset.yaml @@ -0,0 +1,70 @@ +{{- if eq .Values.csp "OpenStack" -}} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: cloud-controller-manager + namespace: {{ .Release.Namespace }} + labels: + k8s-app: cloud-controller-manager +spec: + selector: + matchLabels: + k8s-app: cloud-controller-manager + template: + metadata: + labels: + k8s-app: cloud-controller-manager + spec: + containers: + - name: cloud-controller-manager + image: {{ .Values.OpenStack.image | quote }} + args: + - /bin/openstack-cloud-controller-manager + - --cloud-provider=openstack + - --cloud-config=/etc/config/cloud.conf + - --leader-elect=true + - --allocate-node-cidrs=false + - -v=2 + volumeMounts: + - name: etckubernetes + mountPath: /etc/kubernetes + readOnly: true + - name: etcssl + mountPath: /etc/ssl + readOnly: true + - name: etcpki + mountPath: /etc/pki + readOnly: true + - name: etcconfig + mountPath: /etc/config + readOnly: true + resources: {} + nodeSelector: + node-role.kubernetes.io/control-plane: "" + serviceAccountName: cloud-controller-manager + tolerations: + - effect: NoSchedule + key: node.cloudprovider.kubernetes.io/uninitialized + value: "true" + - effect: NoSchedule + key: node-role.kubernetes.io/master + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/not-ready + volumes: + - name: etckubernetes + hostPath: + path: /etc/kubernetes + - name: etcssl + hostPath: + path: /etc/ssl + - name: etcpki + hostPath: + path: /etc/pki + - name: etcconfig + secret: + secretName: openstackkey + updateStrategy: {} +{{- end -}} diff --git a/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-secret.yaml b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-secret.yaml new file mode 100644 index 000000000..fb93b8bfa --- /dev/null +++ b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/templates/openstack-secret.yaml @@ -0,0 +1,9 @@ +{{- if eq .Values.csp "OpenStack" -}} +apiVersion: v1 +kind: Secret +metadata: + name: openstackkey + namespace: {{ .Release.Namespace }} +data: + cloud.conf: {{ .Values.OpenStack.secretData | b64enc }} +{{- end -}} diff --git a/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/values.schema.json b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/values.schema.json index 44a4f2579..5b537d6b2 100644 --- a/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/values.schema.json +++ b/cli/internal/helm/charts/edgeless/constellation-services/charts/ccm/values.schema.json @@ -3,7 +3,39 @@ "properties": { "csp": { "description": "CSP to which the chart is deployed.", - "enum": ["Azure", "GCP", "AWS", "QEMU"] + "enum": ["AWS", "Azure", "GCP", "OpenStack", "QEMU"] + }, + "AWS": { + "description": "Config values required for deployment on AWS", + "type": "object", + "properties": { + "image": { + "description": "Container image to use for the spawned pods.", + "type": "string" + } + }, + "required": [ + "image" + ] + }, + "Azure": { + "description": "Config values required for deployment on Azure", + "type": "object", + "properties": { + "image": { + "description": "Container image to use for the spawned pods.", + "type": "string", + "examples": ["mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:latest"] + }, + "azureConfig": { + "description": "Base64 encoded json string that hold required config parameters for Azure CCM.", + "type": "string" + } + }, + "required": [ + "image", + "azureConfig" + ] }, "GCP": { "description": "Config values required for deployment on GCP", @@ -41,36 +73,22 @@ "subnetworkPodCIDR" ] }, - "Azure": { - "description": "Config values required for deployment on Azure", + "OpenStack": { + "description": "Config values required for deployment on OpenStack", "type": "object", "properties": { "image": { "description": "Container image to use for the spawned pods.", - "type": "string", - "examples": ["mcr.microsoft.com/oss/kubernetes/azure-cloud-controller-manager:latest"] + "type": "string" }, - "azureConfig": { - "description": "Base64 encoded json string that hold required config parameters for Azure CCM.", + "secretData": { + "description": "OpenStack service account key as a json-string", "type": "string" } }, "required": [ "image", - "azureConfig" - ] - }, - "AWS": { - "description": "Config values required for deployment on AWS", - "type": "object", - "properties": { - "image": { - "description": "Container image to use for the spawned pods.", - "type": "string" - } - }, - "required": [ - "image" + "secretData" ] } }, @@ -80,10 +98,10 @@ "allOf": [ { "if": { - "properties": { "csp": { "const": "GCP" } }, + "properties": { "csp": { "const": "AWS" } }, "required": ["csp"] }, - "then": { "required": ["GCP"] } + "then": { "required": ["AWS"] } }, { "if": { @@ -94,10 +112,17 @@ }, { "if": { - "properties": { "csp": { "const": "AWS" } }, + "properties": { "csp": { "const": "GCP" } }, "required": ["csp"] }, - "then": { "required": ["AWS"] } + "then": { "required": ["GCP"] } + }, + { + "if": { + "properties": { "csp": { "const": "OpenStack" } }, + "required": ["csp"] + }, + "then": { "required": ["OpenStack"] } } ], "title": "Values", diff --git a/cli/internal/helm/charts/edgeless/constellation-services/charts/join-service/values.schema.json b/cli/internal/helm/charts/edgeless/constellation-services/charts/join-service/values.schema.json index 795a590b2..d3908448e 100644 --- a/cli/internal/helm/charts/edgeless/constellation-services/charts/join-service/values.schema.json +++ b/cli/internal/helm/charts/edgeless/constellation-services/charts/join-service/values.schema.json @@ -3,7 +3,7 @@ "properties": { "csp": { "description": "CSP to which the chart is deployed.", - "enum": ["Azure", "GCP", "AWS", "QEMU"] + "enum": ["AWS", "Azure", "GCP", "OpenStack", "QEMU"] }, "measurements": { "description": "JSON-string to describe the expected measurements.", diff --git a/cli/internal/helm/charts/edgeless/constellation-services/values.yaml b/cli/internal/helm/charts/edgeless/constellation-services/values.yaml index a6c4167e2..26bdef388 100644 --- a/cli/internal/helm/charts/edgeless/constellation-services/values.yaml +++ b/cli/internal/helm/charts/edgeless/constellation-services/values.yaml @@ -18,7 +18,8 @@ azure: # Set one of the tags to true to indicate which CSP you are deploying to. tags: + AWS: false Azure: false GCP: false - AWS: false + OpenStack: false QEMU: false diff --git a/cli/internal/helm/loader.go b/cli/internal/helm/loader.go index 5489b3fad..ecf68b150 100644 --- a/cli/internal/helm/loader.go +++ b/cli/internal/helm/loader.go @@ -77,6 +77,8 @@ func NewLoader(csp cloudprovider.Provider, k8sVersion versions.ValidK8sVersion) cnmImage = versions.VersionConfigs[k8sVersion].CloudNodeManagerImageAzure case cloudprovider.GCP: ccmImage = versions.VersionConfigs[k8sVersion].CloudControllerManagerImageGCP + case cloudprovider.OpenStack: + ccmImage = versions.VersionConfigs[k8sVersion].CloudControllerManagerImageOpenStack } return &ChartLoader{ @@ -186,6 +188,8 @@ func (i *ChartLoader) loadCiliumValues() (map[string]any, error) { values = azureVals case cloudprovider.GCP: values = gcpVals + case cloudprovider.OpenStack: + values = openStackVals case cloudprovider.QEMU: values = qemuVals default: @@ -300,6 +304,16 @@ func (i *ChartLoader) loadOperatorsValues() (map[string]any, error) { }, } switch i.csp { + case cloudprovider.AWS: + conOpVals, ok := values["constellation-operator"].(map[string]any) + if !ok { + return nil, errors.New("invalid constellation-operator values") + } + conOpVals["csp"] = "AWS" + + values["tags"] = map[string]any{ + "AWS": true, + } case cloudprovider.Azure: conOpVals, ok := values["constellation-operator"].(map[string]any) if !ok { @@ -320,6 +334,16 @@ func (i *ChartLoader) loadOperatorsValues() (map[string]any, error) { values["tags"] = map[string]any{ "GCP": true, } + case cloudprovider.OpenStack: + conOpVals, ok := values["constellation-operator"].(map[string]any) + if !ok { + return nil, errors.New("invalid constellation-operator values") + } + conOpVals["csp"] = "OpenStack" + + values["tags"] = map[string]any{ + "OpenStack": true, + } case cloudprovider.QEMU: conOpVals, ok := values["constellation-operator"].(map[string]any) if !ok { @@ -330,16 +354,6 @@ func (i *ChartLoader) loadOperatorsValues() (map[string]any, error) { values["tags"] = map[string]any{ "QEMU": true, } - case cloudprovider.AWS: - conOpVals, ok := values["constellation-operator"].(map[string]any) - if !ok { - return nil, errors.New("invalid constellation-operator values") - } - conOpVals["csp"] = "AWS" - - values["tags"] = map[string]any{ - "AWS": true, - } } return values, nil @@ -386,6 +400,18 @@ func (i *ChartLoader) loadConstellationServicesValues() (map[string]any, error) } switch i.csp { + case cloudprovider.AWS: + ccmVals, ok := values["ccm"].(map[string]any) + if !ok { + return nil, errors.New("invalid ccm values") + } + ccmVals["AWS"] = map[string]any{ + "image": i.ccmImage, + } + + values["tags"] = map[string]any{ + "AWS": true, + } case cloudprovider.Azure: ccmVals, ok := values["ccm"].(map[string]any) if !ok { @@ -415,24 +441,23 @@ func (i *ChartLoader) loadConstellationServicesValues() (map[string]any, error) values["tags"] = map[string]any{ "GCP": true, } + case cloudprovider.OpenStack: + ccmVals, ok := values["ccm"].(map[string]any) + if !ok { + return nil, errors.New("invalid ccm values") + } + ccmVals["OpenStack"] = map[string]any{ + "image": i.ccmImage, + } + values["tags"] = map[string]any{ + "OpenStack": true, + } case cloudprovider.QEMU: values["tags"] = map[string]any{ "QEMU": true, } - case cloudprovider.AWS: - ccmVals, ok := values["ccm"].(map[string]any) - if !ok { - return nil, errors.New("invalid ccm values") - } - ccmVals["AWS"] = map[string]any{ - "image": i.ccmImage, - } - - values["tags"] = map[string]any{ - "AWS": true, - } } return values, nil } diff --git a/cli/internal/helm/values.go b/cli/internal/helm/values.go index efc0ef997..eca7ead3c 100644 --- a/cli/internal/helm/values.go +++ b/cli/internal/helm/values.go @@ -121,6 +121,45 @@ var gcpVals = map[string]any{ "kubeProxyReplacementHealthzBindAddr": "0.0.0.0:10256", } +// Values for the Cilium Helm releases for OpenStack. +var openStackVals = map[string]any{ + "endpointRoutes": map[string]any{ + "enabled": true, + }, + "encryption": map[string]any{ + "enabled": true, + "type": "wireguard", + }, + "l7Proxy": false, + "ipam": map[string]any{ + "operator": map[string]any{ + "clusterPoolIPv4PodCIDRList": []string{ + "10.244.0.0/16", + }, + }, + }, + "strictModeCIDR": "10.244.0.0/16", + "image": map[string]any{ + "repository": "ghcr.io/3u13r/cilium", + "suffix": "", + "tag": "v1.12.1-edg", + "digest": "sha256:fdac430143fe719331698b76fbe66410631a21afd3405407d56db260d2d6999b", + "useDigest": true, + }, + "operator": map[string]any{ + "image": map[string]any{ + "repository": "ghcr.io/3u13r/operator", + "tag": "v1.12.1-edg", + "suffix": "", + "genericDigest": "sha256:a225d8d3976fd2a05cfa0c929cd32e60283abedf6bae51db4709df19b2fb70cb", + "useDigest": true, + }, + }, + "kubeProxyReplacement": "strict", + "enableCiliumEndpointSlice": true, + "kubeProxyReplacementHealthzBindAddr": "0.0.0.0:10256", +} + var qemuVals = map[string]any{ "endpointRoutes": map[string]any{ "enabled": true,