| @@ -0,0 +1,46 @@ | |||||
| #!/bin/bash | |||||
| build_folder="$PWD/build" | |||||
| imagebuild_folder="$PWD/imagebuild" | |||||
| yml_folder="$PWD/yml" | |||||
| echo "开始构建agent镜像..." | |||||
| cd "$imagebuild_folder"/agent || exit | |||||
| rm -rf agent | |||||
| rm -rf confs | |||||
| cp -r "$build_folder"/agent . | |||||
| cp -r "$build_folder"/confs . | |||||
| sh build.sh | |||||
| echo "agent镜像构建完成" | |||||
| echo "开始构建coordinator镜像..." | |||||
| cd "$imagebuild_folder"/coordinator || exit | |||||
| rm -rf coordinator | |||||
| rm -rf confs | |||||
| cp -r "$build_folder"/coordinator . | |||||
| cp -r "$build_folder"/confs . | |||||
| sh build.sh | |||||
| echo "coordinator镜像构建完成" | |||||
| echo "开始构建scanner镜像..." | |||||
| cd "$imagebuild_folder"/scanner || exit | |||||
| rm -rf scanner | |||||
| rm -rf confs | |||||
| cp -r "$build_folder"/scanner . | |||||
| cp -r "$build_folder"/confs . | |||||
| sh build.sh | |||||
| echo "scanner镜像构建完成" | |||||
| echo "开始构建client镜像..." | |||||
| cd "$imagebuild_folder"/client || exit | |||||
| rm -rf client | |||||
| rm -rf confs | |||||
| cp -r "$build_folder"/client . | |||||
| cp -r "$build_folder"/confs . | |||||
| sh build.sh | |||||
| echo "client镜像构建完成" | |||||
| echo "全部镜像构建完成" | |||||
| #echo "生成yaml脚本" | |||||
| #cd "$yml_folder" || exit | |||||
| #sh replace.sh | |||||
| @@ -0,0 +1,4 @@ | |||||
| #!/bin/bash | |||||
| docker build -t 10.16.43.85:5010/agentservice-arm64:latest . | |||||
| docker push 10.16.43.85:5010/agentservice-arm64:latest | |||||
| @@ -0,0 +1,4 @@ | |||||
| #!/bin/bash | |||||
| docker build -t 10.16.43.85:5010/clientservice-arm64:latest . | |||||
| docker push 10.16.43.85:5010/clientservice-arm64:latest | |||||
| @@ -0,0 +1,4 @@ | |||||
| #!/bin/bash | |||||
| docker build -t 10.16.43.85:5010/coordinatorservice-arm64:latest . | |||||
| docker push 10.16.43.85:5010/coordinatorservice-arm64:latest | |||||
| @@ -0,0 +1,4 @@ | |||||
| #!/bin/bash | |||||
| docker build -t 10.16.43.85:5010/scannerservice-arm64:latest . | |||||
| docker push 10.16.43.85:5010/scannerservice-arm64:latest | |||||
| @@ -0,0 +1,35 @@ | |||||
| [General] | |||||
| image_registry=10.16.43.85:5010 | |||||
| [agent1] | |||||
| label=octo1 | |||||
| port=32003 | |||||
| node=ecs-c97f-0001 | |||||
| [agent2] | |||||
| label=octo2 | |||||
| port=32004 | |||||
| node=ecs-c97f-0002 | |||||
| [agent3] | |||||
| label=octo3 | |||||
| port=32005 | |||||
| node=ecs-c97f-0003 | |||||
| [agent4] | |||||
| label=octo4 | |||||
| port=32006 | |||||
| node=ecs-c97f-0004 | |||||
| [coordinator] | |||||
| label=pcm00 | |||||
| node=10-9-72-244 | |||||
| [scanner] | |||||
| label=pcm01 | |||||
| node=10-9-72-244 | |||||
| [client] | |||||
| label=pcm2 | |||||
| port=32010 | |||||
| node=10-9-72-244 | |||||
| @@ -0,0 +1,56 @@ | |||||
| # This YAML file contains attacher & csi driver API objects that are necessary | |||||
| # to run external CSI attacher for rclone | |||||
| kind: StatefulSet | |||||
| apiVersion: apps/v1 | |||||
| metadata: | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| spec: | |||||
| serviceName: "csi-controller-rclone" | |||||
| replicas: 1 | |||||
| selector: | |||||
| matchLabels: | |||||
| app: csi-controller-rclone | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: csi-controller-rclone | |||||
| spec: | |||||
| serviceAccountName: csi-controller-rclone | |||||
| containers: | |||||
| - name: csi-attacher | |||||
| #image: k8s.gcr.io/sig-storage/csi-attacher:v3.4.0 | |||||
| image: registry.cn-hangzhou.aliyuncs.com/google_containers/csi-attacher:v3.4.0 | |||||
| args: | |||||
| - "--v=5" | |||||
| - "--csi-address=$(ADDRESS)" | |||||
| - "--leader-election" | |||||
| env: | |||||
| - name: ADDRESS | |||||
| value: /csi/csi.sock | |||||
| imagePullPolicy: "Always" | |||||
| volumeMounts: | |||||
| - name: socket-dir | |||||
| mountPath: /csi | |||||
| - name: rclone | |||||
| image: dvcrn/csi-rclone-reloaded:v1.4.0 | |||||
| image: 10.16.43.85:5010/csi-rclone-reloaded_arm64:v1.4.0 | |||||
| args: | |||||
| - "/bin/csi-rclone-plugin" | |||||
| - "--nodeid=$(NODE_ID)" | |||||
| - "--endpoint=$(CSI_ENDPOINT)" | |||||
| env: | |||||
| - name: NODE_ID | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| - name: CSI_ENDPOINT | |||||
| value: unix://plugin/csi.sock | |||||
| imagePullPolicy: "Always" | |||||
| volumeMounts: | |||||
| - name: socket-dir | |||||
| mountPath: /plugin | |||||
| volumes: | |||||
| - name: socket-dir | |||||
| emptyDir: {} | |||||
| @@ -0,0 +1,106 @@ | |||||
| # This YAML file contains driver-registrar & csi driver nodeplugin API objects | |||||
| # that are necessary to run CSI nodeplugin for rclone | |||||
| kind: DaemonSet | |||||
| apiVersion: apps/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: csi-nodeplugin-rclone | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: csi-nodeplugin-rclone | |||||
| spec: | |||||
| serviceAccountName: csi-nodeplugin-rclone | |||||
| #hostNetwork: true | |||||
| #dnsPolicy: ClusterFirstWithHostNet | |||||
| dnsPolicy: Default | |||||
| containers: | |||||
| - name: node-driver-registrar | |||||
| #image: k8s.gcr.io/sig-storage/csi-node-driver-registrar:v2.4.0 | |||||
| image: registry.cn-hangzhou.aliyuncs.com/google_containers/csi-node-driver-registrar:v2.4.0 | |||||
| lifecycle: | |||||
| preStop: | |||||
| exec: | |||||
| command: | |||||
| [ | |||||
| "/bin/sh", | |||||
| "-c", | |||||
| "rm -rf /registration/csi-rclone /registration/csi-rclone-reg.sock", | |||||
| ] | |||||
| args: | |||||
| - --v=5 | |||||
| - --csi-address=/plugin/csi.sock | |||||
| - --kubelet-registration-path=/var/lib/kubelet/plugins/csi-rclone/csi.sock | |||||
| env: | |||||
| - name: KUBE_NODE_NAME | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| volumeMounts: | |||||
| - name: plugin-dir | |||||
| mountPath: /plugin | |||||
| - name: registration-dir | |||||
| mountPath: /registration | |||||
| - name: rclone | |||||
| securityContext: | |||||
| privileged: true | |||||
| capabilities: | |||||
| add: ["SYS_ADMIN"] | |||||
| allowPrivilegeEscalation: true | |||||
| #image: dvcrn/csi-rclone-reloaded:v1.4.0 | |||||
| image: 10.16.43.85:5010/csi-rclone-reloaded_arm64:v1.4.0 | |||||
| args: | |||||
| - "/bin/csi-rclone-plugin" | |||||
| - "--nodeid=$(NODE_ID)" | |||||
| - "--endpoint=$(CSI_ENDPOINT)" | |||||
| # - "2>&1 > /opt/log/a.log" | |||||
| env: | |||||
| - name: NODE_ID | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| - name: CSI_ENDPOINT | |||||
| value: unix://plugin/csi.sock | |||||
| #- name: RCLONE_LOG_FILE | |||||
| # value: /opt/log/a.log | |||||
| #- name: RCLONE_LOG_LEVEL | |||||
| # value: DEBUG | |||||
| imagePullPolicy: "Always" | |||||
| lifecycle: | |||||
| postStart: | |||||
| exec: | |||||
| command: | |||||
| [ | |||||
| "/bin/sh", | |||||
| "-c", | |||||
| "mount -t fuse.rclone | while read -r mount; do umount $(echo $mount | awk '{print $3}') ; done", | |||||
| ] | |||||
| volumeMounts: | |||||
| - name: plugin-dir | |||||
| mountPath: /plugin | |||||
| - name: pods-mount-dir | |||||
| mountPath: /var/lib/kubelet/pods | |||||
| mountPropagation: "Bidirectional" | |||||
| #- name: test-dir | |||||
| # mountPath: /opt/log | |||||
| volumes: | |||||
| - name: plugin-dir | |||||
| hostPath: | |||||
| path: /var/lib/kubelet/plugins/csi-rclone | |||||
| type: DirectoryOrCreate | |||||
| - name: pods-mount-dir | |||||
| hostPath: | |||||
| path: /var/lib/kubelet/pods | |||||
| type: Directory | |||||
| - hostPath: | |||||
| path: /var/lib/kubelet/plugins_registry | |||||
| type: DirectoryOrCreate | |||||
| name: registration-dir | |||||
| #- name: test-dir | |||||
| # hostPath: | |||||
| # path: /home/pcm/abc | |||||
| # type: DirectoryOrCreate | |||||
| @@ -0,0 +1,49 @@ | |||||
| apiVersion: apps/v1 | |||||
| kind: Deployment | |||||
| metadata: | |||||
| labels: | |||||
| app: client | |||||
| name: client | |||||
| namespace: default | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: client | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: client | |||||
| spec: | |||||
| containers: | |||||
| - name: clientservice | |||||
| image: {{IMAGE_REGISTRY_ADDRESS}}/clientservice-arm64:latest | |||||
| imagePullPolicy: Always | |||||
| volumeMounts: | |||||
| - name: clientconfig | |||||
| mountPath: /opt/confs | |||||
| volumes: | |||||
| - name: clientconfig | |||||
| configMap: | |||||
| name: client-config | |||||
| nodeSelector: | |||||
| nodetype: {{NODE_NAME}} | |||||
| restartPolicy: Always | |||||
| --- | |||||
| apiVersion: v1 | |||||
| kind: Service | |||||
| metadata: | |||||
| labels: | |||||
| app: client | |||||
| name: client | |||||
| namespace: default | |||||
| spec: | |||||
| ports: | |||||
| - port: 7890 | |||||
| protocol: TCP | |||||
| targetPort: 7890 | |||||
| nodePort: {{NODE_PORT}} | |||||
| selector: | |||||
| app: client | |||||
| type: NodePort | |||||
| @@ -0,0 +1,31 @@ | |||||
| apiVersion: apps/v1 | |||||
| kind: Deployment | |||||
| metadata: | |||||
| labels: | |||||
| app: coordinator | |||||
| name: coordinator | |||||
| namespace: default | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: coordinator | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: coordinator | |||||
| spec: | |||||
| containers: | |||||
| - name: coordinatorservice | |||||
| image: {{IMAGE_REGISTRY_ADDRESS}}/coordinatorservice-arm64:latest | |||||
| imagePullPolicy: Always | |||||
| volumeMounts: | |||||
| - name: coordinatorconfig | |||||
| mountPath: /opt/confs | |||||
| volumes: | |||||
| - name: coordinatorconfig | |||||
| configMap: | |||||
| name: coordinator-config | |||||
| nodeSelector: | |||||
| nodetype: {{NODE_NAME}} | |||||
| restartPolicy: Always | |||||
| @@ -0,0 +1,75 @@ | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolumeClaim | |||||
| metadata: | |||||
| name: rclone-{{NODE_NAME}} | |||||
| spec: | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| storageClassName: rclone | |||||
| resources: | |||||
| requests: | |||||
| storage: 10Gi | |||||
| selector: | |||||
| matchLabels: | |||||
| name: rclone-{{NODE_NAME}} | |||||
| --- | |||||
| apiVersion: apps/v1 | |||||
| kind: DaemonSet | |||||
| metadata: | |||||
| labels: | |||||
| app: agent-{{NODE_NAME}} | |||||
| name: agent-{{NODE_NAME}} | |||||
| namespace: default | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: agent-{{NODE_NAME}} | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: agent-{{NODE_NAME}} | |||||
| spec: | |||||
| containers: | |||||
| - name: agentservice | |||||
| image: {{IMAGE_REGISTRY_ADDRESS}}/agentservice-arm64:latest | |||||
| imagePullPolicy: Always | |||||
| #command: ["tail","-f","/etc/hosts"] | |||||
| ports: | |||||
| - containerPort: 5010 | |||||
| protocol: TCP | |||||
| volumeMounts: | |||||
| - name: agentconfig | |||||
| mountPath: /opt/confs | |||||
| - name: rclone-pvc | |||||
| mountPath: /opt/storage | |||||
| volumes: | |||||
| - name: agentconfig | |||||
| configMap: | |||||
| name: agent-{{NODE_NAME}}-config | |||||
| - name: rclone-pvc | |||||
| persistentVolumeClaim: | |||||
| claimName: rclone-{{NODE_NAME}} | |||||
| dnsPolicy: Default | |||||
| nodeSelector: | |||||
| nodetype: {{NODE_NAME}} | |||||
| restartPolicy: Always | |||||
| --- | |||||
| apiVersion: v1 | |||||
| kind: Service | |||||
| metadata: | |||||
| labels: | |||||
| app: agent-{{NODE_NAME}} | |||||
| name: agent-{{NODE_NAME}} | |||||
| namespace: default | |||||
| spec: | |||||
| ports: | |||||
| - port: 5010 | |||||
| protocol: TCP | |||||
| targetPort: 5010 | |||||
| nodePort: {{NODE_PORT}} | |||||
| selector: | |||||
| app: agent-{{NODE_NAME}} | |||||
| type: NodePort | |||||
| @@ -0,0 +1,32 @@ | |||||
| apiVersion: apps/v1 | |||||
| kind: Deployment | |||||
| metadata: | |||||
| labels: | |||||
| app: scanner | |||||
| name: scanner | |||||
| namespace: default | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: scanner | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: scanner | |||||
| spec: | |||||
| containers: | |||||
| - name: scannerservice | |||||
| image: {{IMAGE_REGISTRY_ADDRESS}}/scannerservice-arm64:latest | |||||
| #command: ["tail","-f","/etc/hosts"] | |||||
| imagePullPolicy: Always | |||||
| volumeMounts: | |||||
| - name: scannerconfig | |||||
| mountPath: /opt/confs | |||||
| volumes: | |||||
| - name: scannerconfig | |||||
| configMap: | |||||
| name: scanner-config | |||||
| nodeSelector: | |||||
| nodetype: {{NODE_NAME}} | |||||
| restartPolicy: Always | |||||
| @@ -0,0 +1,6 @@ | |||||
| #FROM scratch | |||||
| FROM alpine:latest | |||||
| COPY . /opt | |||||
| WORKDIR /opt/agent | |||||
| RUN chmod +x agent | |||||
| ENTRYPOINT ["./agent"] | |||||
| @@ -0,0 +1,6 @@ | |||||
| #FROM scratch | |||||
| FROM alpine:latest | |||||
| COPY . /opt | |||||
| WORKDIR /opt/client | |||||
| RUN chmod +x client | |||||
| ENTRYPOINT ["./client","serve","http"] | |||||
| @@ -0,0 +1,12 @@ | |||||
| #FROM scratch | |||||
| FROM alpine:latest | |||||
| COPY . /opt | |||||
| WORKDIR /opt/coordinator | |||||
| RUN apk add --no-cache tzdata | |||||
| ENV TZ=Asia/Shanghai | |||||
| RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone | |||||
| RUN chmod +x coordinator | |||||
| #ENTRYPOINT ["tail","-f","/etc/hosts"] | |||||
| #RUN ./coordinator & | |||||
| #ENTRYPOINT ["tail","-f","log/coordinator.log"] | |||||
| ENTRYPOINT ["./coordinator"] | |||||
| @@ -0,0 +1,9 @@ | |||||
| #FROM scratch | |||||
| FROM alpine:latest | |||||
| COPY . /opt | |||||
| WORKDIR /opt/scanner | |||||
| RUN apk add --no-cache tzdata | |||||
| ENV TZ=Asia/Shanghai | |||||
| RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone | |||||
| RUN chmod +x scanner | |||||
| ENTRYPOINT ["./scanner"] | |||||
| @@ -0,0 +1,42 @@ | |||||
| { | |||||
| "id": 1, | |||||
| "local": { | |||||
| "nodeID": 1, | |||||
| "localIP": "127.0.0.1", | |||||
| "externalIP": "127.0.0.1", | |||||
| "locationID": 1 | |||||
| }, | |||||
| "grpc": { | |||||
| "ip": "127.0.0.1", | |||||
| "port": 5010 | |||||
| }, | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "agent", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| }, | |||||
| "ipfs": { | |||||
| "address": "127.0.0.1:5001" | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a agent" | |||||
| }, | |||||
| "connectivity": { | |||||
| "testInterval": 300 | |||||
| }, | |||||
| "downloader": { | |||||
| "maxStripCacheCount": 100 | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,35 @@ | |||||
| { | |||||
| "local": { | |||||
| "localIP": "127.0.0.1", | |||||
| "externalIP": "127.0.0.1", | |||||
| "locationID": 1 | |||||
| }, | |||||
| "agentGRPC": { | |||||
| "port": 5010 | |||||
| }, | |||||
| "logger": { | |||||
| "output": "stdout", | |||||
| "level": "debug" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| }, | |||||
| "ipfs": null, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a client" | |||||
| }, | |||||
| "connectivity": { | |||||
| "testInterval": 300 | |||||
| }, | |||||
| "downloader": { | |||||
| "maxStripCacheCount": 100 | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,20 @@ | |||||
| { | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "coordinator", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "db": { | |||||
| "address": "127.0.0.1:3306", | |||||
| "account": "root", | |||||
| "password": "123456", | |||||
| "databaseName": "cloudream" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolume | |||||
| metadata: | |||||
| name: rclone-{{NODE_NAME}} | |||||
| labels: | |||||
| name: rclone-{{NODE_NAME}} | |||||
| spec: | |||||
| capacity: | |||||
| storage: 10Gi | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| storageClassName: rclone | |||||
| csi: | |||||
| driver: csi-rclone | |||||
| volumeHandle: rclone-data-id | |||||
| volumeAttributes: | |||||
| remote: "xxxx" | |||||
| remotePath: "xxxx" | |||||
| configData: | | |||||
| [xxxx] | |||||
| type = s3 | |||||
| provider = xxxx | |||||
| access_key_id = xxxx | |||||
| secret_access_key = xxxx | |||||
| endpoint = xxxx | |||||
| @@ -0,0 +1,30 @@ | |||||
| { | |||||
| "ecFileSizeThreshold": 104857600, | |||||
| "nodeUnavailableSeconds": 300, | |||||
| "logger": { | |||||
| "output": "file", | |||||
| "outputFileName": "scanner", | |||||
| "outputDirectory": "log", | |||||
| "level": "debug" | |||||
| }, | |||||
| "db": { | |||||
| "address": "127.0.0.1:3306", | |||||
| "account": "root", | |||||
| "password": "123456", | |||||
| "databaseName": "cloudream" | |||||
| }, | |||||
| "rabbitMQ": { | |||||
| "address": "127.0.0.1:5672", | |||||
| "account": "cloudream", | |||||
| "password": "123456", | |||||
| "vhost": "/" | |||||
| }, | |||||
| "distlock": { | |||||
| "etcdAddress": "127.0.0.1:2379", | |||||
| "etcdUsername": "", | |||||
| "etcdPassword": "", | |||||
| "etcdLockLeaseTimeSec": 5, | |||||
| "randomReleasingDelayMs": 3000, | |||||
| "serviceDescription": "I am a scanner" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,48 @@ | |||||
| # This YAML file contains RBAC API objects that are necessary to run external | |||||
| # CSI attacher for rclone adapter | |||||
| apiVersion: v1 | |||||
| kind: ServiceAccount | |||||
| metadata: | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| --- | |||||
| kind: ClusterRole | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: external-controller-rclone | |||||
| rules: | |||||
| - apiGroups: [""] | |||||
| resources: ["persistentvolumes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["nodes"] | |||||
| verbs: ["get", "list", "watch"] | |||||
| - apiGroups: ["csi.storage.k8s.io"] | |||||
| resources: ["csinodeinfos"] | |||||
| verbs: ["get", "list", "watch"] | |||||
| - apiGroups: ["storage.k8s.io"] | |||||
| resources: ["volumeattachments"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: ["storage.k8s.io"] | |||||
| resources: ["volumeattachments/status"] | |||||
| verbs: ["patch"] | |||||
| - apiGroups: ["coordination.k8s.io"] | |||||
| resources: ["leases"] | |||||
| verbs: ["get", "create", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["events"] | |||||
| verbs: ["create"] | |||||
| --- | |||||
| kind: ClusterRoleBinding | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-attacher-role-rclone | |||||
| subjects: | |||||
| - kind: ServiceAccount | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| roleRef: | |||||
| kind: ClusterRole | |||||
| name: external-controller-rclone | |||||
| apiGroup: rbac.authorization.k8s.io | |||||
| @@ -0,0 +1,8 @@ | |||||
| # this should be deregistered once the controller stops | |||||
| apiVersion: storage.k8s.io/v1 | |||||
| kind: CSIDriver | |||||
| metadata: | |||||
| name: csi-rclone | |||||
| spec: | |||||
| attachRequired: true | |||||
| podInfoOnMount: false # are we sure about this? | |||||
| @@ -0,0 +1,40 @@ | |||||
| # This YAML defines all API objects to create RBAC roles for CSI node plugin | |||||
| apiVersion: v1 | |||||
| kind: ServiceAccount | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| --- | |||||
| kind: ClusterRole | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| rules: | |||||
| - apiGroups: [""] | |||||
| resources: ["persistentvolumes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["secrets", "secret"] | |||||
| verbs: ["get", "list"] | |||||
| - apiGroups: [""] | |||||
| resources: ["nodes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: ["storage.k8s.io"] | |||||
| resources: ["volumeattachments"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["events"] | |||||
| verbs: ["get", "list", "watch", "create", "update", "patch"] | |||||
| --- | |||||
| kind: ClusterRoleBinding | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| subjects: | |||||
| - kind: ServiceAccount | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| roleRef: | |||||
| kind: ClusterRole | |||||
| name: csi-nodeplugin-rclone | |||||
| apiGroup: rbac.authorization.k8s.io | |||||
| @@ -0,0 +1,66 @@ | |||||
| --- | |||||
| # Multiarch build file credits go to Lars Kellogg-Stedman at blog.oddbit.com. If You ever see this - thanks! | |||||
| name: "build images" | |||||
| on: | |||||
| push: | |||||
| branches: | |||||
| - master | |||||
| jobs: | |||||
| docker: | |||||
| runs-on: ubuntu-latest | |||||
| steps: | |||||
| - name: Checkout | |||||
| uses: actions/checkout@v2 | |||||
| - name: Prepare | |||||
| id: prep | |||||
| run: | | |||||
| DOCKER_IMAGE=dvcrn/${GITHUB_REPOSITORY#*/} | |||||
| VERSION=$(cat VERSION) | |||||
| TAGS="${DOCKER_IMAGE}:${VERSION},${DOCKER_IMAGE}:latest" | |||||
| echo ${TAGS} | |||||
| echo ${VERSION} | |||||
| echo ${DOCKER_IMAGE} | |||||
| echo "tags=${TAGS}" >> $GITHUB_ENV | |||||
| echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_ENV | |||||
| - name: Set up QEMU | |||||
| uses: docker/setup-qemu-action@v2 | |||||
| with: | |||||
| platforms: all | |||||
| - name: Set up Docker Buildx | |||||
| id: buildx | |||||
| uses: docker/setup-buildx-action@v2 | |||||
| - name: Login to DockerHub | |||||
| if: github.event_name != 'pull_request' | |||||
| uses: docker/login-action@v2 | |||||
| with: | |||||
| username: dvcrn | |||||
| password: ${{ secrets.DOCKER_PASSWORD }} | |||||
| - name: Build | |||||
| uses: docker/build-push-action@v2 | |||||
| with: | |||||
| builder: ${{ steps.buildx.outputs.name }} | |||||
| context: . | |||||
| file: ./Dockerfile | |||||
| platforms: linux/amd64,linux/arm64 | |||||
| push: true | |||||
| tags: ${{ env.tags }} | |||||
| # - name: Build DM | |||||
| # uses: docker/build-push-action@v2 | |||||
| # with: | |||||
| # builder: ${{ steps.buildx.outputs.name }} | |||||
| # context: . | |||||
| # file: ./Dockerfile.dm | |||||
| # platforms: linux/amd64,linux/arm64 | |||||
| # push: true | |||||
| # tags: ${{ env.tags }} | |||||
| @@ -0,0 +1,3 @@ | |||||
| _output/ | |||||
| .vscode | |||||
| rclone-build/ | |||||
| @@ -0,0 +1,10 @@ | |||||
| # CHANGELOG | |||||
| 1.4.0 (dvcrn): | |||||
| - Merge support for specifying config in secrets: https://github.com/wunderio/csi-rclone/pull/7 | |||||
| - Remove namespace of storageclass | |||||
| - Move all resources into kube-system namespace | |||||
| 1.3.0: | |||||
| - Container init changed to tini | |||||
| - rclone plugin version v1.59.2 | |||||
| @@ -0,0 +1,23 @@ | |||||
| #### | |||||
| FROM golang:alpine AS builder | |||||
| RUN apk update && apk add --no-cache git make bash | |||||
| WORKDIR $GOPATH/src/csi-rclone-nodeplugin | |||||
| COPY . . | |||||
| RUN make plugin | |||||
| #### | |||||
| FROM alpine:3.16 | |||||
| RUN apk add --no-cache ca-certificates bash fuse curl unzip tini | |||||
| RUN curl https://rclone.org/install.sh | bash | |||||
| # Use pre-compiled version (with cirectory marker patch) | |||||
| # https://github.com/rclone/rclone/pull/5323 | |||||
| # COPY bin/rclone /usr/bin/rclone | |||||
| # RUN chmod 755 /usr/bin/rclone \ | |||||
| # && chown root:root /usr/bin/rclone | |||||
| COPY --from=builder /go/src/csi-rclone-nodeplugin/_output/csi-rclone-plugin /bin/csi-rclone-plugin | |||||
| ENTRYPOINT [ "/sbin/tini", "--"] | |||||
| CMD ["/bin/csi-rclone-plugin"] | |||||
| @@ -0,0 +1,23 @@ | |||||
| #### | |||||
| FROM golang:alpine AS builder | |||||
| RUN apk update && apk add --no-cache git make bash | |||||
| WORKDIR $GOPATH/src/csi-rclone-nodeplugin | |||||
| COPY . . | |||||
| RUN make plugin-dm | |||||
| #### | |||||
| FROM alpine:3.16 | |||||
| RUN apk add --no-cache ca-certificates bash fuse curl unzip tini | |||||
| # RUN curl https://rclone.org/install.sh | bash | |||||
| # Use pre-compiled version (with cirectory marker patch) | |||||
| # https://github.com/rclone/rclone/pull/5323 | |||||
| COPY ./install-dm.sh /tmp | |||||
| COPY ./rclone-build /tmp/rclone-build | |||||
| RUN /tmp/install-dm.sh | |||||
| COPY --from=builder /go/src/csi-rclone-nodeplugin/_output/csi-rclone-plugin-dm /bin/csi-rclone-plugin | |||||
| ENTRYPOINT [ "/sbin/tini", "--"] | |||||
| CMD ["/bin/csi-rclone-plugin"] | |||||
| @@ -0,0 +1,202 @@ | |||||
| Apache License | |||||
| Version 2.0, January 2004 | |||||
| http://www.apache.org/licenses/ | |||||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||||
| 1. Definitions. | |||||
| "License" shall mean the terms and conditions for use, reproduction, | |||||
| and distribution as defined by Sections 1 through 9 of this document. | |||||
| "Licensor" shall mean the copyright owner or entity authorized by | |||||
| the copyright owner that is granting the License. | |||||
| "Legal Entity" shall mean the union of the acting entity and all | |||||
| other entities that control, are controlled by, or are under common | |||||
| control with that entity. For the purposes of this definition, | |||||
| "control" means (i) the power, direct or indirect, to cause the | |||||
| direction or management of such entity, whether by contract or | |||||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||||
| outstanding shares, or (iii) beneficial ownership of such entity. | |||||
| "You" (or "Your") shall mean an individual or Legal Entity | |||||
| exercising permissions granted by this License. | |||||
| "Source" form shall mean the preferred form for making modifications, | |||||
| including but not limited to software source code, documentation | |||||
| source, and configuration files. | |||||
| "Object" form shall mean any form resulting from mechanical | |||||
| transformation or translation of a Source form, including but | |||||
| not limited to compiled object code, generated documentation, | |||||
| and conversions to other media types. | |||||
| "Work" shall mean the work of authorship, whether in Source or | |||||
| Object form, made available under the License, as indicated by a | |||||
| copyright notice that is included in or attached to the work | |||||
| (an example is provided in the Appendix below). | |||||
| "Derivative Works" shall mean any work, whether in Source or Object | |||||
| form, that is based on (or derived from) the Work and for which the | |||||
| editorial revisions, annotations, elaborations, or other modifications | |||||
| represent, as a whole, an original work of authorship. For the purposes | |||||
| of this License, Derivative Works shall not include works that remain | |||||
| separable from, or merely link (or bind by name) to the interfaces of, | |||||
| the Work and Derivative Works thereof. | |||||
| "Contribution" shall mean any work of authorship, including | |||||
| the original version of the Work and any modifications or additions | |||||
| to that Work or Derivative Works thereof, that is intentionally | |||||
| submitted to Licensor for inclusion in the Work by the copyright owner | |||||
| or by an individual or Legal Entity authorized to submit on behalf of | |||||
| the copyright owner. For the purposes of this definition, "submitted" | |||||
| means any form of electronic, verbal, or written communication sent | |||||
| to the Licensor or its representatives, including but not limited to | |||||
| communication on electronic mailing lists, source code control systems, | |||||
| and issue tracking systems that are managed by, or on behalf of, the | |||||
| Licensor for the purpose of discussing and improving the Work, but | |||||
| excluding communication that is conspicuously marked or otherwise | |||||
| designated in writing by the copyright owner as "Not a Contribution." | |||||
| "Contributor" shall mean Licensor and any individual or Legal Entity | |||||
| on behalf of whom a Contribution has been received by Licensor and | |||||
| subsequently incorporated within the Work. | |||||
| 2. Grant of Copyright License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| copyright license to reproduce, prepare Derivative Works of, | |||||
| publicly display, publicly perform, sublicense, and distribute the | |||||
| Work and such Derivative Works in Source or Object form. | |||||
| 3. Grant of Patent License. Subject to the terms and conditions of | |||||
| this License, each Contributor hereby grants to You a perpetual, | |||||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||||
| (except as stated in this section) patent license to make, have made, | |||||
| use, offer to sell, sell, import, and otherwise transfer the Work, | |||||
| where such license applies only to those patent claims licensable | |||||
| by such Contributor that are necessarily infringed by their | |||||
| Contribution(s) alone or by combination of their Contribution(s) | |||||
| with the Work to which such Contribution(s) was submitted. If You | |||||
| institute patent litigation against any entity (including a | |||||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | |||||
| or a Contribution incorporated within the Work constitutes direct | |||||
| or contributory patent infringement, then any patent licenses | |||||
| granted to You under this License for that Work shall terminate | |||||
| as of the date such litigation is filed. | |||||
| 4. Redistribution. You may reproduce and distribute copies of the | |||||
| Work or Derivative Works thereof in any medium, with or without | |||||
| modifications, and in Source or Object form, provided that You | |||||
| meet the following conditions: | |||||
| (a) You must give any other recipients of the Work or | |||||
| Derivative Works a copy of this License; and | |||||
| (b) You must cause any modified files to carry prominent notices | |||||
| stating that You changed the files; and | |||||
| (c) You must retain, in the Source form of any Derivative Works | |||||
| that You distribute, all copyright, patent, trademark, and | |||||
| attribution notices from the Source form of the Work, | |||||
| excluding those notices that do not pertain to any part of | |||||
| the Derivative Works; and | |||||
| (d) If the Work includes a "NOTICE" text file as part of its | |||||
| distribution, then any Derivative Works that You distribute must | |||||
| include a readable copy of the attribution notices contained | |||||
| within such NOTICE file, excluding those notices that do not | |||||
| pertain to any part of the Derivative Works, in at least one | |||||
| of the following places: within a NOTICE text file distributed | |||||
| as part of the Derivative Works; within the Source form or | |||||
| documentation, if provided along with the Derivative Works; or, | |||||
| within a display generated by the Derivative Works, if and | |||||
| wherever such third-party notices normally appear. The contents | |||||
| of the NOTICE file are for informational purposes only and | |||||
| do not modify the License. You may add Your own attribution | |||||
| notices within Derivative Works that You distribute, alongside | |||||
| or as an addendum to the NOTICE text from the Work, provided | |||||
| that such additional attribution notices cannot be construed | |||||
| as modifying the License. | |||||
| You may add Your own copyright statement to Your modifications and | |||||
| may provide additional or different license terms and conditions | |||||
| for use, reproduction, or distribution of Your modifications, or | |||||
| for any such Derivative Works as a whole, provided Your use, | |||||
| reproduction, and distribution of the Work otherwise complies with | |||||
| the conditions stated in this License. | |||||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | |||||
| any Contribution intentionally submitted for inclusion in the Work | |||||
| by You to the Licensor shall be under the terms and conditions of | |||||
| this License, without any additional terms or conditions. | |||||
| Notwithstanding the above, nothing herein shall supersede or modify | |||||
| the terms of any separate license agreement you may have executed | |||||
| with Licensor regarding such Contributions. | |||||
| 6. Trademarks. This License does not grant permission to use the trade | |||||
| names, trademarks, service marks, or product names of the Licensor, | |||||
| except as required for reasonable and customary use in describing the | |||||
| origin of the Work and reproducing the content of the NOTICE file. | |||||
| 7. Disclaimer of Warranty. Unless required by applicable law or | |||||
| agreed to in writing, Licensor provides the Work (and each | |||||
| Contributor provides its Contributions) on an "AS IS" BASIS, | |||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||||
| implied, including, without limitation, any warranties or conditions | |||||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||||
| PARTICULAR PURPOSE. You are solely responsible for determining the | |||||
| appropriateness of using or redistributing the Work and assume any | |||||
| risks associated with Your exercise of permissions under this License. | |||||
| 8. Limitation of Liability. In no event and under no legal theory, | |||||
| whether in tort (including negligence), contract, or otherwise, | |||||
| unless required by applicable law (such as deliberate and grossly | |||||
| negligent acts) or agreed to in writing, shall any Contributor be | |||||
| liable to You for damages, including any direct, indirect, special, | |||||
| incidental, or consequential damages of any character arising as a | |||||
| result of this License or out of the use or inability to use the | |||||
| Work (including but not limited to damages for loss of goodwill, | |||||
| work stoppage, computer failure or malfunction, or any and all | |||||
| other commercial damages or losses), even if such Contributor | |||||
| has been advised of the possibility of such damages. | |||||
| 9. Accepting Warranty or Additional Liability. While redistributing | |||||
| the Work or Derivative Works thereof, You may choose to offer, | |||||
| and charge a fee for, acceptance of support, warranty, indemnity, | |||||
| or other liability obligations and/or rights consistent with this | |||||
| License. However, in accepting such obligations, You may act only | |||||
| on Your own behalf and on Your sole responsibility, not on behalf | |||||
| of any other Contributor, and only if You agree to indemnify, | |||||
| defend, and hold each Contributor harmless for any liability | |||||
| incurred by, or claims asserted against, such Contributor by reason | |||||
| of your accepting any such warranty or additional liability. | |||||
| END OF TERMS AND CONDITIONS | |||||
| APPENDIX: How to apply the Apache License to your work. | |||||
| To apply the Apache License to your work, attach the following | |||||
| boilerplate notice, with the fields enclosed by brackets "[]" | |||||
| replaced with your own identifying information. (Don't include | |||||
| the brackets!) The text should be enclosed in the appropriate | |||||
| comment syntax for the file format. We also recommend that a | |||||
| file or class name and description of purpose be included on the | |||||
| same "printed page" as the copyright notice for easier | |||||
| identification within third-party archives. | |||||
| Copyright [yyyy] [name of copyright owner] | |||||
| 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. | |||||
| @@ -0,0 +1,54 @@ | |||||
| # Copyright 2017 The Kubernetes Authors. | |||||
| # | |||||
| # 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. | |||||
| VERSION=$(shell cat VERSION) | |||||
| REGISTRY_NAME=dvcrn | |||||
| IMAGE_NAME=csi-rclone-reloaded | |||||
| IMAGE_TAG=$(REGISTRY_NAME)/$(IMAGE_NAME):$(VERSION) | |||||
| .PHONY: all rclone-plugin clean rclone-container | |||||
| all: plugin container push | |||||
| dm: plugin-dm container-dm push-dm | |||||
| plugin: | |||||
| go mod download | |||||
| CGO_ENABLED=0 GOOS=linux go build -a -gcflags=-trimpath=$(go env GOPATH) -asmflags=-trimpath=$(go env GOPATH) -ldflags '-X github.com/wunderio/csi-rclone/pkg/rclone.DriverVersion=$(VERSION) -extldflags "-static"' -o _output/csi-rclone-plugin ./cmd/csi-rclone-plugin | |||||
| plugin-dm: | |||||
| go mod download | |||||
| CGO_ENABLED=0 GOOS=linux go build -a -gcflags=-trimpath=$(go env GOPATH) -asmflags=-trimpath=$(go env GOPATH) -ldflags '-X github.com/wunderio/csi-rclone/pkg/rclone.DriverVersion=$(VERSION)-dm -extldflags "-static"' -o _output/csi-rclone-plugin-dm ./cmd/csi-rclone-plugin | |||||
| container: | |||||
| docker build -t $(IMAGE_TAG) -f ./cmd/csi-rclone-plugin/Dockerfile . | |||||
| container-dm: | |||||
| docker build -t $(IMAGE_TAG)-dm -f ./cmd/csi-rclone-plugin/Dockerfile.dm . | |||||
| push: | |||||
| docker push $(IMAGE_TAG) | |||||
| push-dm: | |||||
| docker push $(IMAGE_TAG)-dm | |||||
| buildx: | |||||
| docker buildx build --platform linux/amd64,linux/arm64 --push -t $(IMAGE_TAG) -f ./cmd/csi-rclone-plugin/Dockerfile . | |||||
| buildx-dm: | |||||
| docker buildx build --platform linux/amd64,linux/arm64 --push -t $(IMAGE_TAG)-dm -f ./cmd/csi-rclone-plugin/Dockerfile.dm . | |||||
| clean: | |||||
| go clean -r -x | |||||
| -rm -rf _output | |||||
| @@ -0,0 +1,185 @@ | |||||
| # CSI rclone mount plugin | |||||
| Fork of https://github.com/wunderio/csi-rclone that is a bit slow with merging PRs | |||||
| Differences with that fork: | |||||
| - Everything is under kube-system namespace | |||||
| - Allow specifying of secrets for PV | |||||
| - StorageClass is no longer namespaced | |||||
| This project implements Container Storage Interface (CSI) plugin that allows using [rclone mount](https://rclone.org/) as storage backend. Rclone mount points and [parameters](https://rclone.org/commands/rclone_mount/) can be configured using Secret or PersistentVolume volumeAttibutes. | |||||
| ## Kubernetes cluster compatability | |||||
| Works (tested): | |||||
| - `deploy/kubernetes/1.19`: K8S>= 1.19.x (due to storage.k8s.io/v1 CSIDriver API) | |||||
| - `deploy/kubernetes/1.13`: K8S 1.13.x - 1.21.x (storage.k8s.io/v1beta1 CSIDriver API) | |||||
| Does not work: | |||||
| - v1.12.7-gke.10, driver name csi-rclone not found in the list of registered CSI drivers | |||||
| ## Installing CSI driver to kubernetes cluster | |||||
| TLDR: ` kubectl apply -f deploy/kubernetes/1.19` (or `deploy/kubernetes/1.13` for older version) to get the CSI setup | |||||
| ### Example: Adding Dropbox through rclone | |||||
| The easiest way to use this is to specify your rclone configuration inside the PV: | |||||
| ```yaml | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolume | |||||
| metadata: | |||||
| name: rclone-dropbox | |||||
| labels: | |||||
| name: rclone-dropbox | |||||
| spec: | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| capacity: | |||||
| storage: 10Gi | |||||
| storageClassName: rclone | |||||
| csi: | |||||
| driver: csi-rclone | |||||
| volumeHandle: rclone-dropbox-data-id | |||||
| volumeAttributes: | |||||
| remote: "dropbox" | |||||
| remotePath: "" | |||||
| configData: | | |||||
| [dropbox] | |||||
| type = dropbox | |||||
| client_id = xxx | |||||
| client_secret = xxx | |||||
| token = {"access_token":"xxx","token_type":"bearer","refresh_token":"xxx","expiry":"xxx"} | |||||
| --- | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolumeClaim | |||||
| metadata: | |||||
| name: rclone-dropbox | |||||
| spec: | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| resources: | |||||
| requests: | |||||
| storage: 10Gi | |||||
| storageClassName: rclone | |||||
| selector: | |||||
| matchLabels: | |||||
| name: rclone-dropbox | |||||
| ``` | |||||
| (to get access token, setup Dropbox locally with rclone first, then copy whatever `rclone config show` gives you) | |||||
| ### Example: S3 storage without direct rclone configuration | |||||
| ```yaml | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolume | |||||
| metadata: | |||||
| name: rclone-wasabi | |||||
| labels: | |||||
| name: rclone-wasabi | |||||
| spec: | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| capacity: | |||||
| storage: 1000Gi | |||||
| storageClassName: rclone | |||||
| csi: | |||||
| driver: csi-rclone | |||||
| volumeHandle: data-id | |||||
| volumeAttributes: | |||||
| remote: "bucketname" | |||||
| remotePath: "" | |||||
| s3-provider: "Wasabi" | |||||
| s3-endpoint: "https://s3.ap-southeast-1.wasabisys.com" | |||||
| s3-access-key-id: "xxx" | |||||
| s3-secret-access-key: "xxx" | |||||
| --- | |||||
| <pvc manifest here> | |||||
| ``` | |||||
| ### Example: Using a secret (thanks to [wunderio/csi-rclone#7](https://github.com/wunderio/csi-rclone/pull/7)) | |||||
| _Note:_ secrets act as defaults, you can still override keys in your PV definitions. | |||||
| _Note 2_: Use `secret-rclone` as global default for when there are no secrets defined, for example if you always want the same S3 credentials across your PVs | |||||
| _Note 3_: Secrets need to be in the same namespace as the csi controller, so if you used the default of this repository, add it to `kube-system` | |||||
| ```yaml | |||||
| apiVersion: v1 | |||||
| kind: Secret | |||||
| metadata: | |||||
| name: my-secret | |||||
| namespace: kube-system # <-- secret needs to be in kube-system namespace, same as CSI controller | |||||
| type: Opaque | |||||
| stringData: | |||||
| remote: "my-s3" | |||||
| remotePath: "projectname" | |||||
| configData: | | |||||
| [my-s3] | |||||
| type = s3 | |||||
| provider = Minio | |||||
| access_key_id = ACCESS_KEY_ID | |||||
| secret_access_key = SECRET_ACCESS_KEY | |||||
| endpoint = http://minio-release.default:9000 | |||||
| ``` | |||||
| Then specify it into the PV: | |||||
| ```yaml | |||||
| apiVersion: v1 | |||||
| kind: PersistentVolume | |||||
| metadata: | |||||
| name: rclone-dropbox | |||||
| labels: | |||||
| name: rclone-dropbox | |||||
| spec: | |||||
| accessModes: | |||||
| - ReadWriteMany | |||||
| capacity: | |||||
| storage: 10Gi | |||||
| storageClassName: rclone | |||||
| csi: | |||||
| driver: csi-rclone | |||||
| volumeHandle: rclone-dropbox-data-id | |||||
| volumeAttributes: | |||||
| secretName: "my-secret" | |||||
| ``` | |||||
| ## Debugging & logs | |||||
| - After creating a pod, if something goes wrong you should be able to see it using `kubectl describe <pod>` | |||||
| - Check logs of the controller: `kubectl logs -f -l app=csi-nodeplugin-rclone --namespace kube-system -c rclone` | |||||
| ## Building plugin and creating image | |||||
| Current code is referencing projects repository on github.com. If you fork the repository, you have to change go includes in several places (use search and replace). | |||||
| 1. First push the changed code to remote. The build will use paths from `pkg/` directory. | |||||
| 2. Build the plugin | |||||
| ``` | |||||
| make plugin | |||||
| ``` | |||||
| 3. Build the container and inject the plugin into it. | |||||
| ``` | |||||
| make container | |||||
| ``` | |||||
| 4. Change docker.io account in `Makefile` and use `make push` to push the image to remote. | |||||
| ``` | |||||
| make push | |||||
| ``` | |||||
| ## Changelog | |||||
| See [CHANGELOG.txt](CHANGELOG.txt) | |||||
| @@ -0,0 +1 @@ | |||||
| v1.4.0 | |||||
| @@ -0,0 +1,15 @@ | |||||
| FROM alpine:3.16 | |||||
| RUN apk add --no-cache ca-certificates bash fuse curl unzip tini | |||||
| RUN curl https://rclone.org/install.sh | bash | |||||
| # Use pre-compiled version (with cirectory marker patch) | |||||
| # https://github.com/rclone/rclone/pull/5323 | |||||
| # COPY bin/rclone /usr/bin/rclone | |||||
| # RUN chmod 755 /usr/bin/rclone \ | |||||
| # && chown root:root /usr/bin/rclone | |||||
| COPY ./_output/csi-rclone-plugin /bin/csi-rclone-plugin | |||||
| ENTRYPOINT [ "/sbin/tini", "--"] | |||||
| CMD ["/bin/csi-rclone-plugin"] | |||||
| @@ -0,0 +1,15 @@ | |||||
| FROM alpine:3.16 | |||||
| RUN apk add --no-cache ca-certificates bash fuse curl unzip tini | |||||
| # RUN curl https://rclone.org/install.sh | bash | |||||
| # Use pre-compiled version (with cirectory marker patch) | |||||
| # https://github.com/rclone/rclone/pull/5323 | |||||
| COPY ./install-dm.sh /tmp | |||||
| COPY ./rclone-build /tmp/rclone-build | |||||
| RUN /tmp/install-dm.sh | |||||
| COPY ./_output/csi-rclone-plugin-dm /bin/csi-rclone-plugin | |||||
| ENTRYPOINT [ "/sbin/tini", "--"] | |||||
| CMD ["/bin/csi-rclone-plugin"] | |||||
| @@ -0,0 +1,65 @@ | |||||
| package main | |||||
| import ( | |||||
| "flag" | |||||
| "fmt" | |||||
| "os" | |||||
| "github.com/spf13/cobra" | |||||
| "github.com/wunderio/csi-rclone/pkg/rclone" | |||||
| ) | |||||
| var ( | |||||
| endpoint string | |||||
| nodeID string | |||||
| ) | |||||
| func init() { | |||||
| flag.Set("logtostderr", "true") | |||||
| } | |||||
| func main() { | |||||
| flag.CommandLine.Parse([]string{}) | |||||
| cmd := &cobra.Command{ | |||||
| Use: "rclone", | |||||
| Short: "CSI based rclone driver", | |||||
| Run: func(cmd *cobra.Command, args []string) { | |||||
| handle() | |||||
| }, | |||||
| } | |||||
| cmd.Flags().AddGoFlagSet(flag.CommandLine) | |||||
| cmd.PersistentFlags().StringVar(&nodeID, "nodeid", "", "node id") | |||||
| cmd.MarkPersistentFlagRequired("nodeid") | |||||
| cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "", "CSI endpoint") | |||||
| cmd.MarkPersistentFlagRequired("endpoint") | |||||
| versionCmd := &cobra.Command{ | |||||
| Use: "version", | |||||
| Short: "Prints information about this version of csi rclone plugin", | |||||
| Run: func(cmd *cobra.Command, args []string) { | |||||
| fmt.Printf(`csi-rclone plugin | |||||
| Version: %s | |||||
| `, rclone.DriverVersion) | |||||
| }, | |||||
| } | |||||
| cmd.AddCommand(versionCmd) | |||||
| versionCmd.ResetFlags() | |||||
| cmd.ParseFlags(os.Args[1:]) | |||||
| if err := cmd.Execute(); err != nil { | |||||
| fmt.Fprintf(os.Stderr, "%s", err.Error()) | |||||
| os.Exit(1) | |||||
| } | |||||
| os.Exit(0) | |||||
| } | |||||
| func handle() { | |||||
| d := rclone.NewDriver(nodeID, endpoint) | |||||
| d.Run() | |||||
| } | |||||
| @@ -0,0 +1,66 @@ | |||||
| # This YAML file contains RBAC API objects that are necessary to run external | |||||
| # CSI attacher for rclone adapter | |||||
| apiVersion: v1 | |||||
| kind: ServiceAccount | |||||
| metadata: | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| --- | |||||
| kind: ClusterRole | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: external-controller-rclone | |||||
| rules: | |||||
| - apiGroups: [""] | |||||
| resources: ["persistentvolumes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["nodes"] | |||||
| verbs: ["get", "list", "watch"] | |||||
| - apiGroups: ["csi.storage.k8s.io"] | |||||
| resources: ["csinodeinfos"] | |||||
| verbs: ["get", "list", "watch"] | |||||
| - apiGroups: ["storage.k8s.io"] | |||||
| resources: ["volumeattachments"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| --- | |||||
| kind: ClusterRoleBinding | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-attacher-role-rclone | |||||
| subjects: | |||||
| - kind: ServiceAccount | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| roleRef: | |||||
| kind: ClusterRole | |||||
| name: external-controller-rclone | |||||
| apiGroup: rbac.authorization.k8s.io | |||||
| --- | |||||
| kind: ClusterRole | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-cluster-driver-registrar-role | |||||
| rules: | |||||
| - apiGroups: ["csi.storage.k8s.io"] | |||||
| resources: ["csidrivers"] | |||||
| verbs: ["create", "delete"] | |||||
| - apiGroups: ["apiextensions.k8s.io"] | |||||
| resources: ["customresourcedefinitions"] | |||||
| verbs: ["create", "list", "watch", "delete"] | |||||
| --- | |||||
| kind: ClusterRoleBinding | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-cluster-driver-registrar-binding | |||||
| subjects: | |||||
| - kind: ServiceAccount | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| roleRef: | |||||
| kind: ClusterRole | |||||
| name: csi-cluster-driver-registrar-role | |||||
| apiGroup: rbac.authorization.k8s.io | |||||
| @@ -0,0 +1,65 @@ | |||||
| # This YAML file contains attacher & csi driver API objects that are necessary | |||||
| # to run external CSI attacher for rclone | |||||
| kind: StatefulSet | |||||
| apiVersion: apps/v1 | |||||
| metadata: | |||||
| name: csi-controller-rclone | |||||
| namespace: kube-system | |||||
| spec: | |||||
| serviceName: "csi-controller-rclone" | |||||
| replicas: 1 | |||||
| selector: | |||||
| matchLabels: | |||||
| app: csi-controller-rclone | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: csi-controller-rclone | |||||
| spec: | |||||
| serviceAccountName: csi-controller-rclone | |||||
| containers: | |||||
| - name: csi-attacher | |||||
| image: quay.io/k8scsi/csi-attacher:v1.1.1 | |||||
| args: | |||||
| - "--v=5" | |||||
| - "--csi-address=$(ADDRESS)" | |||||
| env: | |||||
| - name: ADDRESS | |||||
| value: /csi/csi.sock | |||||
| imagePullPolicy: "Always" | |||||
| volumeMounts: | |||||
| - name: socket-dir | |||||
| mountPath: /csi | |||||
| - name: csi-cluster-driver-registrar | |||||
| image: quay.io/k8scsi/csi-cluster-driver-registrar:v1.0.1 | |||||
| args: | |||||
| - "--v=5" | |||||
| - '--pod-info-mount-version="v1"' | |||||
| - "--csi-address=$(ADDRESS)" | |||||
| env: | |||||
| - name: ADDRESS | |||||
| value: /csi/csi.sock | |||||
| volumeMounts: | |||||
| - name: socket-dir | |||||
| mountPath: /csi | |||||
| - name: rclone | |||||
| image: dvcrn/csi-rclone-reloaded:v1.4.0 | |||||
| args: | |||||
| - "/bin/csi-rclone-plugin" | |||||
| - "--nodeid=$(NODE_ID)" | |||||
| - "--endpoint=$(CSI_ENDPOINT)" | |||||
| env: | |||||
| - name: NODE_ID | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| - name: CSI_ENDPOINT | |||||
| value: unix://plugin/csi.sock | |||||
| imagePullPolicy: "Always" | |||||
| volumeMounts: | |||||
| - name: socket-dir | |||||
| mountPath: /plugin | |||||
| volumes: | |||||
| - name: socket-dir | |||||
| emptyDir: {} | |||||
| @@ -0,0 +1,40 @@ | |||||
| # This YAML defines all API objects to create RBAC roles for CSI node plugin | |||||
| apiVersion: v1 | |||||
| kind: ServiceAccount | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| --- | |||||
| kind: ClusterRole | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| rules: | |||||
| - apiGroups: [""] | |||||
| resources: ["persistentvolumes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["secrets", "secret"] | |||||
| verbs: ["get", "list"] | |||||
| - apiGroups: [""] | |||||
| resources: ["nodes"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: ["storage.k8s.io"] | |||||
| resources: ["volumeattachments"] | |||||
| verbs: ["get", "list", "watch", "update"] | |||||
| - apiGroups: [""] | |||||
| resources: ["events"] | |||||
| verbs: ["get", "list", "watch", "create", "update", "patch"] | |||||
| --- | |||||
| kind: ClusterRoleBinding | |||||
| apiVersion: rbac.authorization.k8s.io/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| subjects: | |||||
| - kind: ServiceAccount | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| roleRef: | |||||
| kind: ClusterRole | |||||
| name: csi-nodeplugin-rclone | |||||
| apiGroup: rbac.authorization.k8s.io | |||||
| @@ -0,0 +1,92 @@ | |||||
| # This YAML file contains driver-registrar & csi driver nodeplugin API objects | |||||
| # that are necessary to run CSI nodeplugin for rclone | |||||
| kind: DaemonSet | |||||
| apiVersion: apps/v1 | |||||
| metadata: | |||||
| name: csi-nodeplugin-rclone | |||||
| namespace: kube-system | |||||
| spec: | |||||
| selector: | |||||
| matchLabels: | |||||
| app: csi-nodeplugin-rclone | |||||
| template: | |||||
| metadata: | |||||
| labels: | |||||
| app: csi-nodeplugin-rclone | |||||
| spec: | |||||
| serviceAccountName: csi-nodeplugin-rclone | |||||
| hostNetwork: true | |||||
| dnsPolicy: ClusterFirstWithHostNet | |||||
| containers: | |||||
| - name: node-driver-registrar | |||||
| image: quay.io/k8scsi/csi-node-driver-registrar:v1.1.0 | |||||
| lifecycle: | |||||
| preStop: | |||||
| exec: | |||||
| command: | |||||
| [ | |||||
| "/bin/sh", | |||||
| "-c", | |||||
| "rm -rf /registration/csi-rclone /registration/csi-rclone-reg.sock", | |||||
| ] | |||||
| args: | |||||
| - --v=5 | |||||
| - --csi-address=/plugin/csi.sock | |||||
| - --kubelet-registration-path=/var/lib/kubelet/plugins/csi-rclone/csi.sock | |||||
| env: | |||||
| - name: KUBE_NODE_NAME | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| volumeMounts: | |||||
| - name: plugin-dir | |||||
| mountPath: /plugin | |||||
| - name: registration-dir | |||||
| mountPath: /registration | |||||
| - name: rclone | |||||
| securityContext: | |||||
| privileged: true | |||||
| capabilities: | |||||
| add: ["SYS_ADMIN"] | |||||
| allowPrivilegeEscalation: true | |||||
| image: dvcrn/csi-rclone-reloaded:v1.4.0 | |||||
| args: | |||||
| - "/bin/csi-rclone-plugin" | |||||
| - "--nodeid=$(NODE_ID)" | |||||
| - "--endpoint=$(CSI_ENDPOINT)" | |||||
| env: | |||||
| - name: NODE_ID | |||||
| valueFrom: | |||||
| fieldRef: | |||||
| fieldPath: spec.nodeName | |||||
| - name: CSI_ENDPOINT | |||||
| value: unix://plugin/csi.sock | |||||
| imagePullPolicy: "Always" | |||||
| lifecycle: | |||||
| postStart: | |||||
| exec: | |||||
| command: | |||||
| [ | |||||
| "/bin/sh", | |||||
| "-c", | |||||
| "mount -t fuse.rclone | while read -r mount; do umount $(echo $mount | awk '{print $3}') ; done", | |||||
| ] | |||||
| volumeMounts: | |||||
| - name: plugin-dir | |||||
| mountPath: /plugin | |||||
| - name: pods-mount-dir | |||||
| mountPath: /var/lib/kubelet/pods | |||||
| mountPropagation: "Bidirectional" | |||||
| volumes: | |||||
| - name: plugin-dir | |||||
| hostPath: | |||||
| path: /var/lib/kubelet/plugins/csi-rclone | |||||
| type: DirectoryOrCreate | |||||
| - name: pods-mount-dir | |||||
| hostPath: | |||||
| path: /var/lib/kubelet/pods | |||||
| type: Directory | |||||
| - hostPath: | |||||
| path: /var/lib/kubelet/plugins_registry | |||||
| type: DirectoryOrCreate | |||||
| name: registration-dir | |||||