# Copyright 2022 DigitalOcean # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Install the CSI Driver. This simplifies driver discovery and enables us to # customize Kubernetes behavior # https://kubernetes-csi.github.io/docs/csi-driver-object.html apiVersion: storage.k8s.io/v1 kind: CSIDriver metadata: name: dobs.csi.digitalocean.com spec: attachRequired: true podInfoOnMount: true --- kind: VolumeSnapshotClass apiVersion: snapshot.storage.k8s.io/v1 metadata: name: do-block-storage annotations: snapshot.storage.kubernetes.io/is-default-class: "true" driver: dobs.csi.digitalocean.com deletionPolicy: Delete --- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: do-block-storage annotations: storageclass.kubernetes.io/is-default-class: "true" provisioner: dobs.csi.digitalocean.com allowVolumeExpansion: true --- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: do-block-storage-retain provisioner: dobs.csi.digitalocean.com reclaimPolicy: Retain allowVolumeExpansion: true --- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: do-block-storage-xfs provisioner: dobs.csi.digitalocean.com parameters: fstype: xfs allowVolumeExpansion: true --- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: do-block-storage-xfs-retain provisioner: dobs.csi.digitalocean.com parameters: fstype: xfs reclaimPolicy: Retain allowVolumeExpansion: true --- ############################################## ########### ############ ########### Controller plugin ############ ########### ############ ############################################## kind: StatefulSet apiVersion: apps/v1 metadata: name: csi-do-controller namespace: kube-system spec: serviceName: "csi-do" selector: matchLabels: app: csi-do-controller replicas: 1 template: metadata: annotations: kubectl.kubernetes.io/default-container: csi-do-plugin labels: app: csi-do-controller role: csi-do spec: priorityClassName: system-cluster-critical serviceAccount: csi-do-controller-sa containers: - name: csi-provisioner image: registry.k8s.io/sig-storage/csi-provisioner:v3.3.0 args: - "--csi-address=$(ADDRESS)" - "--default-fstype=ext4" - "--v=5" env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock imagePullPolicy: "IfNotPresent" volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ - name: csi-attacher image: registry.k8s.io/sig-storage/csi-attacher:v4.0.0 args: - "--csi-address=$(ADDRESS)" - "--v=5" - "--reconcile-sync=30m" - "--timeout=2m" env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock imagePullPolicy: "IfNotPresent" volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ - name: csi-snapshotter image: registry.k8s.io/sig-storage/csi-snapshotter:v6.1.0 args: - "--csi-address=$(ADDRESS)" - "--v=5" env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock imagePullPolicy: IfNotPresent volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ - name: csi-resizer image: registry.k8s.io/sig-storage/csi-resizer:v1.6.0 args: - "--csi-address=$(ADDRESS)" - "--timeout=30s" - "--v=5" # DO volumes support online resize. - "--handle-volume-inuse-error=false" env: - name: ADDRESS value: /var/lib/csi/sockets/pluginproxy/csi.sock imagePullPolicy: "IfNotPresent" volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ - name: csi-do-plugin image: digitalocean/do-csi-plugin:v4.4.1 args : - "--endpoint=$(CSI_ENDPOINT)" - "--token=$(DIGITALOCEAN_ACCESS_TOKEN)" - "--url=$(DIGITALOCEAN_API_URL)" - "--default-volumes-page-size=200" env: - name: CSI_ENDPOINT value: unix:///var/lib/csi/sockets/pluginproxy/csi.sock - name: DIGITALOCEAN_API_URL value: https://api.digitalocean.com/ - name: DIGITALOCEAN_ACCESS_TOKEN valueFrom: secretKeyRef: name: digitalocean key: access-token imagePullPolicy: "Always" volumeMounts: - name: socket-dir mountPath: /var/lib/csi/sockets/pluginproxy/ volumes: - name: socket-dir emptyDir: {} --- kind: ServiceAccount apiVersion: v1 metadata: name: csi-do-controller-sa namespace: kube-system --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-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: ["snapshot.storage.k8s.io"] resources: ["volumesnapshots"] verbs: ["get", "list"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents"] verbs: ["get", "list"] - apiGroups: [ "storage.k8s.io" ] resources: [ "csinodes" ] verbs: [ "get", "list", "watch" ] - apiGroups: [ "" ] resources: [ "nodes" ] verbs: [ "get", "list", "watch" ] - apiGroups: ["storage.k8s.io"] resources: ["volumeattachments"] verbs: ["get", "list", "watch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-provisioner-binding subjects: - kind: ServiceAccount name: csi-do-controller-sa namespace: kube-system roleRef: kind: ClusterRole name: csi-do-provisioner-role apiGroup: rbac.authorization.k8s.io --- # Attacher must be able to work with PVs, nodes and VolumeAttachments kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-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-do-attacher-binding subjects: - kind: ServiceAccount name: csi-do-controller-sa namespace: kube-system roleRef: kind: ClusterRole name: csi-do-attacher-role apiGroup: rbac.authorization.k8s.io --- # Snapshotter sidecar kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-snapshotter-role rules: - apiGroups: [""] resources: ["events"] verbs: ["list", "watch", "create", "update", "patch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotclasses"] verbs: ["get", "list", "watch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents"] verbs: ["get", "list", "watch", "update", "patch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents/status"] verbs: ["update", "patch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-snapshotter-binding subjects: - kind: ServiceAccount name: csi-do-controller-sa namespace: kube-system roleRef: kind: ClusterRole name: csi-do-snapshotter-role apiGroup: rbac.authorization.k8s.io --- # Resizer must be able to work with PVCs, PVs, SCs. kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-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"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-resizer-binding subjects: - kind: ServiceAccount name: csi-do-controller-sa namespace: kube-system roleRef: kind: ClusterRole name: csi-do-resizer-role apiGroup: rbac.authorization.k8s.io --- ######################################## ########### ############ ########### Node plugin ############ ########### ############ ######################################## kind: DaemonSet apiVersion: apps/v1 metadata: name: csi-do-node namespace: kube-system spec: selector: matchLabels: app: csi-do-node template: metadata: annotations: kubectl.kubernetes.io/default-container: csi-do-plugin labels: app: csi-do-node role: csi-do spec: priorityClassName: system-node-critical serviceAccount: csi-do-node-sa hostNetwork: true initContainers: # Delete automount udev rule running on all DO droplets. The rule mounts # devices briefly and may conflict with CSI-managed droplets (leading to # "resource busy" errors). We can safely delete it in DOKS. # - name: automount-udev-deleter # image: alpine:3 # args: # - "rm" # - "-f" # - "/etc/udev/rules.d/99-digitalocean-automount.rules" # volumeMounts: # - name: udev-rules-dir # mountPath: /etc/udev/rules.d/ containers: - name: csi-node-driver-registrar image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.6.0 args: - "--v=5" - "--csi-address=$(ADDRESS)" - "--kubelet-registration-path=$(DRIVER_REG_SOCK_PATH)" lifecycle: preStop: exec: command: ["/bin/sh", "-c", "rm -rf /registration/dobs.csi.digitalocean.com /registration/dobs.csi.digitalocean.com-reg.sock"] env: - name: ADDRESS value: /csi/csi.sock - name: DRIVER_REG_SOCK_PATH value: /var/lib/kubelet/plugins/dobs.csi.digitalocean.com/csi.sock - name: KUBE_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName volumeMounts: - name: plugin-dir mountPath: /csi/ - name: registration-dir mountPath: /registration/ - name: csi-do-plugin image: digitalocean/do-csi-plugin:v4.4.1 args : - "--endpoint=$(CSI_ENDPOINT)" - "--url=$(DIGITALOCEAN_API_URL)" env: - name: CSI_ENDPOINT value: unix:///csi/csi.sock - name: DIGITALOCEAN_API_URL value: https://api.digitalocean.com/ imagePullPolicy: "Always" securityContext: privileged: true capabilities: add: ["SYS_ADMIN"] allowPrivilegeEscalation: true volumeMounts: - name: plugin-dir mountPath: /csi - name: pods-mount-dir mountPath: /var/lib/kubelet # needed so that any mounts setup inside this container are # propagated back to the host machine. mountPropagation: "Bidirectional" - name: device-dir mountPath: /dev volumes: - name: registration-dir hostPath: path: /var/lib/kubelet/plugins_registry/ type: DirectoryOrCreate - name: plugin-dir hostPath: path: /var/lib/kubelet/plugins/dobs.csi.digitalocean.com type: DirectoryOrCreate - name: pods-mount-dir hostPath: path: /var/lib/kubelet type: Directory - name: device-dir hostPath: path: /dev # - name: udev-rules-dir # hostPath: # path: /etc/udev/rules.d/ --- apiVersion: v1 kind: ServiceAccount metadata: name: csi-do-node-sa namespace: kube-system --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-node-driver-registrar-role namespace: kube-system rules: - apiGroups: [""] resources: ["events"] verbs: ["get", "list", "watch", "create", "update", "patch"] --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: csi-do-node-driver-registrar-binding subjects: - kind: ServiceAccount name: csi-do-node-sa namespace: kube-system roleRef: kind: ClusterRole name: csi-do-node-driver-registrar-role apiGroup: rbac.authorization.k8s.io