AB#2554 GCP CSI driver deployment (#532)

* Allow enabling/disabling of CSI driver through config

* Fix inconsistent namespace parsing

* Deploy GCP CSI driver on init

* Update invalid pod tolerations

* Add generate script for CSI charts

* Update generateCilium script

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2022-11-18 10:05:02 +01:00 committed by GitHub
parent 6b7e470983
commit b966f57a2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 1597 additions and 165 deletions

View file

@ -35,3 +35,13 @@ dependencies:
- Azure
- GCP
- AWS
- name: gcp-compute-persistent-disk-csi-driver
version: 1.0.1
condition: gcp.deployCSIDriver
tags:
- GCP
- name: csi-azuredisk
version: 1.0.1
condition: azure.deployCSIDriver
tags:
- Azure

View file

@ -14,4 +14,4 @@ roleRef:
subjects:
- kind: ServiceAccount
name: constellation-cluster-autoscaler
namespace: kube-system
namespace: {{ .Release.Namespace }}

View file

@ -45,8 +45,7 @@ spec:
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Equal
value: "true"
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists

View file

@ -0,0 +1,5 @@
apiVersion: v2
appVersion: "v1.0.1"
description: Azure disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support
name: csi-azuredisk
version: v1.0.1

View file

@ -0,0 +1,5 @@
apiVersion: v2
version: 1.0.1
appVersion: "v1.0.1"
description: GCP Compute Persistent Disk Container Storage Interface (CSI) Storage Plugin with on-node encryption support
name: gcp-compute-persistent-disk-csi-driver

View file

@ -0,0 +1,308 @@
##### Node Service Account, Roles, RoleBindings
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-node-sa
namespace: {{ .Release.Namespace }}
---
##### Controller Service Account, Roles, Rolebindings
apiVersion: v1
kind: ServiceAccount
metadata:
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
# xref: https://github.com/kubernetes-csi/external-provisioner/blob/master/deploy/kubernetes/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-provisioner-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshots"]
verbs: ["get", "list"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["get", "list"]
# Access to volumeattachments is only needed when the CSI driver
# has the PUBLISH_UNPUBLISH_VOLUME controller capability.
# In that case, external-provisioner will watch volumeattachments
# to determine when it is safe to delete a volume.
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-provisioner-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-provisioner-role
apiGroup: rbac.authorization.k8s.io
---
# xref: https://github.com/kubernetes-csi/external-attacher/blob/master/deploy/kubernetes/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-attacher-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["csinodes"]
verbs: ["get", "list", "watch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: ["storage.k8s.io"]
resources: ["volumeattachments/status"]
verbs: ["patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-attacher-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-attacher-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-controller
value: 900000000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver controller deployment only."
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: csi-gce-pd-node
value: 900001000
globalDefault: false
description: "This priority class should be used for the GCE PD CSI driver node deployment only."
---
# Resizer must be able to work with PVCs, PVs, SCs.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-role
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumeclaims/status"]
verbs: ["update", "patch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
# If handle-volume-inuse-error=true, the pod specific rbac is needed
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-resizer-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-resizer-role
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-deploy
rules:
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
verbs: ["use"]
resourceNames:
- csi-gce-pd-controller-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller-deploy
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-controller-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-node-deploy
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- csi-gce-pd-node-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-node
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-node-sa
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: csi-gce-pd-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: csi-gce-pd-node-deploy
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csi-gce-pd-snapshotter-role
rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
# Secrets resource omitted since GCE PD snapshots does not require them
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents"]
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
- apiGroups: ["snapshot.storage.k8s.io"]
resources: ["volumesnapshotcontents/status"]
verbs: ["update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-snapshotter-binding
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: ClusterRole
name: csi-gce-pd-snapshotter-role
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-leaderelection-role
namespace: {{ .Release.Namespace }}
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "watch", "list", "delete", "update", "create"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: csi-gce-pd-controller-leaderelection-binding
namespace: {{ .Release.Namespace }}
labels:
k8s-app: gcp-compute-persistent-disk-csi-driver
subjects:
- kind: ServiceAccount
name: csi-gce-pd-controller-sa
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: csi-gce-pd-leaderelection-role
apiGroup: rbac.authorization.k8s.io

View file

@ -0,0 +1,175 @@
kind: Deployment
apiVersion: apps/v1
metadata:
name: csi-gce-pd-controller
namespace: {{ .Release.Namespace }}
spec:
replicas: {{ .Values.csiController.replicas }}
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
{{- if .Values.csiController.runOnControlPlane }}
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Exists
- effect: NoSchedule
key: node.cloudprovider.kubernetes.io/uninitialized
operator: Exists
- effect: NoSchedule
key: node.kubernetes.io/not-ready
operator: Exists
{{- end }}
nodeSelector:
kubernetes.io/os: linux
{{- if .Values.csiController.runOnControlPlane }}
node-role.kubernetes.io/control-plane: ""
{{- end }}
serviceAccountName: csi-gce-pd-controller-sa
priorityClassName: csi-gce-pd-controller
containers:
- name: csi-provisioner
image: {{ .Values.image.csiProvisioner.repo }}:{{ .Values.image.csiProvisioner.tag }}
imagePullPolicy: {{ .Values.image.csiProvisioner.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--feature-gates=Topology=true"
- "--http-endpoint=:22011"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
- "--extra-create-metadata"
# - "--run-controller-service=false" # disable the controller service of the CSI driver
# - "--run-node-service=false" # disable the node service of the CSI driver
- "--leader-election"
- "--default-fstype=ext4"
- "--controller-publish-readonly=true"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22011
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-attacher
image: {{ .Values.image.csiAttacher.repo }}:{{ .Values.image.csiAttacher.tag }}
imagePullPolicy: {{ .Values.image.csiAttacher.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22012"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22012
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-resizer
image: {{ .Values.image.csiResizer.repo }}:{{ .Values.image.csiResizer.tag }}
imagePullPolicy: {{ .Values.image.csiResizer.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--http-endpoint=:22013"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--handle-volume-inuse-error=false"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 22013
name: http-endpoint
protocol: TCP
livenessProbe:
failureThreshold: 1
httpGet:
path: /healthz/leader-election
port: http-endpoint
initialDelaySeconds: 10
timeoutSeconds: 10
periodSeconds: 20
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: csi-snapshotter
image: {{ .Values.image.csiSnapshotter.repo }}:{{ .Values.image.csiSnapshotter.tag }}
imagePullPolicy: {{ .Values.image.csiSnapshotter.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--metrics-address=:22014"
- "--leader-election"
- "--leader-election-namespace=$(PDCSI_NAMESPACE)"
- "--timeout=450s"
env:
- name: PDCSI_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: gce-pd-driver
# Don't change base image without changing pdImagePlaceholder in
# test/k8s-integration/main.go
image: {{ .Values.image.gcepdDriver.repo }}:{{ .Values.image.gcepdDriver.tag }}
imagePullPolicy: {{ .Values.image.gcepdDriver.pullPolicy }}
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
env:
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/etc/cloud-sa/key.json"
volumeMounts:
- name: socket-dir
mountPath: /csi
- name: cloud-sa-volume
readOnly: true
mountPath: "/etc/cloud-sa"
volumes:
- name: socket-dir
emptyDir: {}
- name: cloud-sa-volume
secret:
secretName: gcekey

View file

@ -0,0 +1,117 @@
kind: DaemonSet
apiVersion: apps/v1
metadata:
name: csi-gce-pd-node
namespace: {{ .Release.Namespace }}
spec:
selector:
matchLabels:
app: gcp-compute-persistent-disk-csi-driver
template:
metadata:
labels:
app: gcp-compute-persistent-disk-csi-driver
spec:
priorityClassName: csi-gce-pd-node
serviceAccountName: csi-gce-pd-node-sa
nodeSelector:
kubernetes.io/os: linux
containers:
- name: csi-driver-registrar
image: {{ .Values.image.csiNodeRegistrar.repo }}:{{ .Values.image.csiNodeRegistrar.tag }}
imagePullPolicy: {{ .Values.image.csiNodeRegistrar.pullPolicy }}
args:
- "--v=5"
- "--csi-address=/csi/csi.sock"
- "--kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock"
env:
- name: KUBE_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
volumeMounts:
- name: plugin-dir
mountPath: /csi
- name: registration-dir
mountPath: /registration
livenessProbe:
initialDelaySeconds: 3
exec:
command:
- /csi-node-driver-registrar
- --kubelet-registration-path=/var/lib/kubelet/plugins/gcp.csi.confidential.cloud/csi.sock
- --mode=kubelet-registration-probe
- name: gce-pd-driver
image: {{ .Values.image.gcepdDriver.repo }}:{{ .Values.image.gcepdDriver.tag }}
imagePullPolicy: {{ .Values.image.gcepdDriver.pullPolicy }}
args:
- "--v=5"
- "--endpoint=unix:/csi/csi.sock"
- "--run-controller-service=false"
- "--kms-addr=kms.{{ .Values.csiNode.kmsNamespace | default .Release.Namespace }}:{{ .Values.csiNode.kmsPort }}"
securityContext:
privileged: true
volumeMounts:
- name: kubelet-dir
mountPath: /var/lib/kubelet
mountPropagation: "Bidirectional"
- name: plugin-dir
mountPath: /csi
- name: device-dir
mountPath: /dev
# The following mounts are required to trigger host udevadm from
# container
- name: udev-rules-etc
mountPath: /etc/udev
- name: udev-rules-lib
mountPath: /lib/udev
- name: udev-socket
mountPath: /run/udev
- name: sys
mountPath: /sys
- name: cryptsetup
mountPath: /run/cryptsetup
volumes:
- name: registration-dir
hostPath:
path: /var/lib/kubelet/plugins_registry/
type: Directory
- name: kubelet-dir
hostPath:
path: /var/lib/kubelet
type: Directory
- name: plugin-dir
hostPath:
path: /var/lib/kubelet/plugins/gcp.csi.confidential.cloud/
type: DirectoryOrCreate
- name: device-dir
hostPath:
path: /dev
type: Directory
# The following mounts are required to trigger host udevadm from
# container
- name: udev-rules-etc
hostPath:
path: /etc/udev
type: Directory
- name: udev-rules-lib
hostPath:
path: /lib/udev
type: Directory
- name: udev-socket
hostPath:
path: /run/udev
type: Directory
- name: sys
hostPath:
path: /sys
type: Directory
- name: cryptsetup
hostPath:
path: /run/cryptsetup
type: Directory
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
# See "special case". This will tolerate everything. Node component should
# be scheduled on all nodes.
tolerations:
- operator: Exists

View file

@ -0,0 +1,14 @@
{{- if .Values.createStorageClass }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
name: encrypted-rwo
parameters:
type: pd-standard
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: true
reclaimPolicy: Delete
volumeBindingMode: Immediate
{{- end }}

View file

@ -0,0 +1,14 @@
{{- if .Values.createStorageClass }}
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
name: integrity-encrypted-rwo
parameters:
type: pd-ssd
csi.storage.k8s.io/fstype: ext4-integrity
provisioner: gcp.csi.confidential.cloud
allowVolumeExpansion: false
reclaimPolicy: Delete
volumeBindingMode: Immediate
{{- end }}

View file

@ -0,0 +1,7 @@
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: gcp.csi.confidential.cloud
spec:
attachRequired: true
podInfoOnMount: false

View file

@ -0,0 +1,36 @@
image:
csiProvisioner:
repo: k8s.gcr.io/sig-storage/csi-provisioner
tag: "v3.1.0"
pullPolicy: IfNotPresent
csiAttacher:
repo: k8s.gcr.io/sig-storage/csi-attacher
tag: "v3.4.0"
pullPolicy: IfNotPresent
csiResizer:
repo: k8s.gcr.io/sig-storage/csi-resizer
tag: "v1.4.0"
pullPolicy: IfNotPresent
csiSnapshotter:
repo: k8s.gcr.io/sig-storage/csi-snapshotter
tag: "v4.0.1"
pullPolicy: IfNotPresent
csiNodeRegistrar:
repo: k8s.gcr.io/sig-storage/csi-node-driver-registrar
tag: "v2.5.0"
pullPolicy: IfNotPresent
gcepdDriver:
repo: ghcr.io/edgelesssys/constellation/gcp-csi-driver
# CSI driver version is independent of Constellation releases
tag: "v1.0.0"
pullPolicy: IfNotPresent
csiController:
replicas: 1
runOnControlPlane: true
csiNode:
kmsPort: "9000"
kmsNamespace: "kube-system"
createStorageClass: true

View file

@ -2,7 +2,7 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: join-config
namespace: kube-system
namespace: {{ .Release.Namespace }}
data:
# mustToJson is required so the json-strings passed from go are of type string in the rendered yaml.
enforcedPCRs: {{ .Values.enforcedPCRs | mustToJson }}

View file

@ -23,8 +23,7 @@ spec:
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Equal
value: "true"
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists
@ -39,7 +38,7 @@ spec:
image: {{ .Values.image }}
args:
- --cloud-provider={{ .Values.csp }}
- --kms-endpoint=kms.kube-system:{{ .Values.global.kmsPort }}
- --kms-endpoint=kms.{{ .Release.Namespace }}:{{ .Values.global.kmsPort }}
volumeMounts:
- mountPath: {{ .Values.global.serviceBasePath }}
name: config

View file

@ -1,5 +1,3 @@
# Namespace to which to deploy
namespace: "kube-system"
csp: "gcp"
joinServicePort: 9090
joinServiceNodePort: 30090

View file

@ -35,8 +35,7 @@ spec:
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/master
operator: Equal
value: "true"
operator: Exists
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Exists

View file

@ -1,5 +1,3 @@
# Namespace to which KMS will be deployed.
namespace: "kube-system"
# Name of the key within the respective secret that holds the salt.
saltKeyName: salt
# Name of the secret that contains the master secret.

View file

@ -10,6 +10,14 @@ global:
# Name of the ConfigMap that holds configs that should not be modified by the user.
internalCMName: internal-config
# GCP specific configuration
gcp:
deployCSIDriver: false
# Azure specific configuration
azure:
deployCSIDriver: false
# Set one of the tags to true to indicate which CSP you are deploying to.
tags:
Azure: false