diff --git a/charts/aws-ebs-csi-driver/templates/node-windows.yaml b/charts/aws-ebs-csi-driver/templates/node-windows.yaml new file mode 100644 index 0000000000..9408db42d0 --- /dev/null +++ b/charts/aws-ebs-csi-driver/templates/node-windows.yaml @@ -0,0 +1,169 @@ +kind: DaemonSet +apiVersion: apps/v1 +metadata: + name: ebs-csi-node-windows + namespace: kube-system + labels: + {{- include "aws-ebs-csi-driver.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + app: ebs-csi-node + {{- include "aws-ebs-csi-driver.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + app: ebs-csi-node + {{- include "aws-ebs-csi-driver.labels" . | nindent 8 }} + {{- if .Values.node.podAnnotations }} + annotations: {{ toYaml .Values.node.podAnnotations | nindent 8 }} + {{- end }} + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: eks.amazonaws.com/compute-type + operator: NotIn + values: + - fargate + nodeSelector: + kubernetes.io/os: windows + {{- with .Values.node.nodeSelector }} +{{ toYaml . | indent 8 }} + {{- end }} + # hostNetwork: true + serviceAccountName: {{ .Values.serviceAccount.node.name }} + priorityClassName: {{ .Values.node.priorityClassName | default "system-cluster-critical" }} + tolerations: + {{- if .Values.node.tolerateAllTaints }} + - operator: Exists + {{- end }} + {{- with .Values.node.tolerations }} +{{ toYaml . | indent 8 }} + {{- end }} + containers: + - name: ebs-plugin + image: public.ecr.aws/b5w6x5z2/aws-ebs-csi-driver:windows + imagePullPolicy: Always + args: + - node + - --endpoint=$(CSI_ENDPOINT) + {{- if .Values.volumeAttachLimit }} + - --volume-attach-limit={{ .Values.volumeAttachLimit }} + {{- end }} + - --logtostderr + - --v=5 + env: + - name: CSI_ENDPOINT + value: unix:/csi/csi.sock + volumeMounts: + - name: kubelet-dir + mountPath: C:\var\lib\kubelet + mountPropagation: "None" + - name: plugin-dir + mountPath: C:\csi + - name: csi-proxy-disk-pipe + mountPath: \\.\pipe\csi-proxy-disk-v1beta2 + - name: csi-proxy-volume-pipe + mountPath: \\.\pipe\csi-proxy-volume-v1beta2 + - name: csi-proxy-filesystem-pipe + mountPath: \\.\pipe\csi-proxy-filesystem-v1beta1 + ports: + - name: healthz + containerPort: 9808 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: healthz + initialDelaySeconds: 10 + timeoutSeconds: 3 + periodSeconds: 10 + failureThreshold: 5 + {{- if .Values.node.resources }} + {{- with .Values.node.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- else }} + {{- with .Values.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + - name: node-driver-registrar + image: {{ printf "%s:%s" .Values.sidecars.nodeDriverRegistrarImage.repository .Values.sidecars.nodeDriverRegistrarImage.tag }} + args: + - --csi-address=$(ADDRESS) + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + - --v=5 + lifecycle: + preStop: + exec: + command: ["/bin/sh", "-c", "rm -rf /registration/ebs.csi.aws.com-reg.sock /csi/csi.sock"] + env: + - name: ADDRESS + value: unix:/csi/csi.sock + - name: DRIVER_REG_SOCK_PATH + value: C:\var\lib\kubelet\plugins\ebs.csi.aws.com\csi.sock + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + - name: registration-dir + mountPath: C:\registration + {{- if .Values.node.resources }} + {{- with .Values.node.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- else }} + {{- with .Values.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + - name: liveness-probe + image: {{ printf "%s:%s" .Values.sidecars.livenessProbeImage.repository .Values.sidecars.livenessProbeImage.tag }} + args: + - --csi-address=unix:/csi/csi.sock + volumeMounts: + - name: plugin-dir + mountPath: C:\csi + {{- if .Values.node.resources }} + {{- with .Values.node.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- else }} + {{- with .Values.resources }} + resources: {{ toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{- range .Values.imagePullSecrets }} + - name: {{ . }} + {{- end }} + {{- end }} + volumes: + - name: kubelet-dir + hostPath: + path: C:\var\lib\kubelet + type: Directory + - name: plugin-dir + hostPath: + path: C:\var\lib\kubelet\plugins\ebs.csi.aws.com + type: DirectoryOrCreate + - name: registration-dir + hostPath: + path: C:\var\lib\kubelet\plugins_registry + type: Directory + - name: csi-proxy-disk-pipe + hostPath: + path: \\.\pipe\csi-proxy-disk-v1beta2 + type: "" + - name: csi-proxy-volume-pipe + hostPath: + path: \\.\pipe\csi-proxy-volume-v1beta2 + type: "" + - name: csi-proxy-filesystem-pipe + hostPath: + path: \\.\pipe\csi-proxy-filesystem-v1beta1 + type: "" diff --git a/examples/kubernetes/windows/README.md b/examples/kubernetes/windows/README.md new file mode 100644 index 0000000000..3402fc5010 --- /dev/null +++ b/examples/kubernetes/windows/README.md @@ -0,0 +1,72 @@ +## Windows + +**This example requires pre-release versions of csi-proxy and the driver that do not exist yet. It is intended for developers only for now.** + +This example shows how to create a EBS volume and consume it from a Windows container dynamically. + + +## Prerequisites + +1. A 1.18+ Windows node. Windows support has only been tested on 1.18 EKS Windows nodes. https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html +2. [csi-proxy](https://github.com/kubernetes-csi/csi-proxy) vX.Y.Z+ (TODO: no such version exists yet) installed on the Windows node. +3. The driver vX.Y.Z+ (TODO: no such version exists yet) Node plugin (DaemonSet) installed on the Windows node. +4. The driver vX.Y.Z+ (TODO: no such version exists yet) Controller plugin (Deployment) installed on a Linux node. The Controller hasn't been tested on Windows. + +## Usage + +1. Create a sample app along with the StorageClass and the PersistentVolumeClaim: +``` +kubectl apply -f specs/ +``` + +2. Validate the volume was created and `volumeHandle` contains an EBS volumeID: +``` +kubectl describe pv +``` + +3. Validate the pod can write data to the volume: +``` +kubectl exec -it windows-server-iis-7c5fc8f6c5-t5mk9 -- powershell + +PS C:\> New-Item -Path data -Name "testfile1.txt" -ItemType "file" -Value "This +is a text string." + + + Directory: C:\data + + +Mode LastWriteTime Length Name +---- ------------- ------ ---- +-a---- 4/7/2021 12:31 AM 22 testfile1.txt +``` + +4. Validate a different pod can read data from the volume: +``` +kubectl delete po windows-server-iis-7c5fc8f6c5-t5mk9 + +kubectl exec -it windows-server-iis-7c5fc8f6c5-j44qv -- powershell + +PS C:\> ls data + + + Directory: C:\data + + +Mode LastWriteTime Length Name +---- ------------- ------ ---- +-a---- 4/7/2021 12:31 AM 22 testfile1.txt +``` + +5. OPTIONAL: In case you want to run some e2e tests with Windows pods, make sure to cordon Linux nodes for the duration of the test and modify the vpc-admission-webhook so that the Pods created as part of the tests get scheduled to the Windows nodes. +``` +kubectl cordon -l kubernetes.io/os=linux +# edit the webhook such that OSLabelSelectorOverride=all +kubectl edit deployment -n kube-system vpc-admission-webhook +deployment.apps/vpc-admission-webhook edited +ginkgo -nodes=1 -v --focus="External.Storage.*default.fs.*should.store.data" ./tests/e2e-kubernetes/ -- -kubeconfig=$KUBECONFIG -gce-zone=us-west-2a -node-os-distro=windows +``` + +6. Cleanup resources: +``` +kubectl delete -f specs/ +``` diff --git a/examples/kubernetes/windows/specs/windows.yaml b/examples/kubernetes/windows/specs/windows.yaml new file mode 100644 index 0000000000..855f45c4da --- /dev/null +++ b/examples/kubernetes/windows/specs/windows.yaml @@ -0,0 +1,76 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: windows-server-iis +spec: + selector: + matchLabels: + app: windows-server-iis + tier: backend + track: stable + replicas: 1 + template: + metadata: + labels: + app: windows-server-iis + tier: backend + track: stable + spec: + containers: + - name: windows-server-iis + image: mcr.microsoft.com/windows/servercore:1809 + ports: + - name: http + containerPort: 80 + imagePullPolicy: IfNotPresent + command: + - powershell.exe + - -command + - "Add-WindowsFeature Web-Server; Invoke-WebRequest -UseBasicParsing -Uri 'https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe' -OutFile 'C:\\ServiceMonitor.exe'; echo '

Hello EKS!!!

' > C:\\inetpub\\wwwroot\\default.html; C:\\ServiceMonitor.exe 'w3svc'; " + volumeMounts: + - name: persistent-storage + mountPath: C:\data + nodeSelector: + kubernetes.io/os: windows + volumes: + - name: persistent-storage + persistentVolumeClaim: + claimName: ebs-claim +--- +apiVersion: v1 +kind: Service +metadata: + name: windows-server-iis-service + namespace: default +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 80 + selector: + app: windows-server-iis + tier: backend + track: stable + sessionAffinity: None + type: LoadBalancer +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: ebs-claim +spec: + storageClassName: windows + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 4Gi +--- +kind: StorageClass +apiVersion: storage.k8s.io/v1 +metadata: + name: windows +provisioner: ebs.csi.aws.com +volumeBindingMode: WaitForFirstConsumer +parameters: + fstype: ntfs