├── Deploy ├── Trident │ ├── bundle.yaml │ ├── kustomization.yaml │ ├── namespace.yaml │ └── tridentorchestrator.yaml └── crds │ ├── kustomization.yaml │ └── tridentorchestrator_crd.yaml ├── Helm └── trident │ ├── .helmignore │ ├── Chart.yaml │ ├── crds │ └── tridentorchestrator_crd.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── bundle.yaml │ └── tridentorchestrator.yaml │ └── values.yaml ├── License ├── NOTICE ├── Samples ├── Backend │ ├── backend-sample.json │ └── backend-sample.yaml ├── Secret │ └── smb_user_secret.yaml ├── Snapshot │ ├── VolumeSnapshot.yaml │ └── VolumeSnapshotClass.yaml ├── StorageClass │ ├── sc_iscsi_sample.yaml.yaml │ └── sc_smb_sample.yaml ├── Volumes │ ├── clone │ │ ├── pvc-clone-file.yaml │ │ ├── pvc-clone-from-snap-file.yaml │ │ ├── pvc-clone.yaml │ │ └── pvc-snap.yaml │ ├── import │ │ ├── pvc-import-file.yaml │ │ └── pvc-import.yaml │ ├── normal │ │ ├── pvc-any.yaml │ │ ├── pvc-backend.yaml │ │ ├── pvc-block.yaml │ │ ├── pvc-file.yaml │ │ ├── pvc-hero.yaml │ │ └── pvc-raid.yaml │ ├── pvc-clone.yaml │ ├── pvc-from-snapshot.yaml │ ├── pvc-import.yaml │ └── pvc-sample.yaml └── pod.yaml ├── VolumeSnapshot ├── kustomization.yaml ├── rbac-snapshot-controller.yaml ├── setup-snapshot-controller.yaml ├── snapshot.storage.k8s.io_volumesnapshotclasses.yaml ├── snapshot.storage.k8s.io_volumesnapshotcontents.yaml └── snapshot.storage.k8s.io_volumesnapshots.yaml ├── bin ├── linux-amd64 │ └── tridentctl └── linux-arm64 │ └── tridentctl └── readme.md /Deploy/Trident/bundle.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app: operator.trident.qnap.io 6 | name: trident-operator 7 | namespace: trident 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: ClusterRole 11 | metadata: 12 | creationTimestamp: null 13 | labels: 14 | app: operator.trident.qnap.io 15 | name: trident-operator 16 | rules: 17 | # Permissions same as Trident 18 | - apiGroups: 19 | - "" 20 | resources: 21 | - namespaces 22 | verbs: 23 | - get 24 | - list 25 | - apiGroups: 26 | - "" 27 | resources: 28 | - persistentvolumes 29 | - persistentvolumeclaims 30 | verbs: 31 | - get 32 | - list 33 | - watch 34 | - create 35 | - delete 36 | - update 37 | - patch 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - persistentvolumeclaims/status 42 | verbs: 43 | - update 44 | - patch 45 | - apiGroups: 46 | - storage.k8s.io 47 | resources: 48 | - storageclasses 49 | verbs: 50 | - get 51 | - list 52 | - watch 53 | - create 54 | - delete 55 | - update 56 | - patch 57 | - apiGroups: 58 | - "" 59 | resources: 60 | - events 61 | verbs: 62 | - get 63 | - list 64 | - watch 65 | - create 66 | - update 67 | - patch 68 | - apiGroups: 69 | - "" 70 | resources: 71 | - secrets 72 | verbs: 73 | - get 74 | - list 75 | - watch 76 | - create 77 | - delete 78 | - update 79 | - patch 80 | - apiGroups: 81 | - "" 82 | resources: 83 | - resourcequotas 84 | verbs: 85 | - get 86 | - list 87 | - watch 88 | - create 89 | - delete 90 | - update 91 | - patch 92 | - apiGroups: 93 | - "" 94 | resources: 95 | - pods 96 | verbs: 97 | - get 98 | - list 99 | - watch 100 | - create 101 | - delete 102 | - update 103 | - patch 104 | - apiGroups: 105 | - "" 106 | resources: 107 | - pods/log 108 | verbs: 109 | - get 110 | - list 111 | - watch 112 | - apiGroups: 113 | - "" 114 | resources: 115 | - nodes 116 | verbs: 117 | - get 118 | - list 119 | - watch 120 | - update 121 | - apiGroups: 122 | - storage.k8s.io 123 | resources: 124 | - volumeattachments 125 | verbs: 126 | - get 127 | - list 128 | - watch 129 | - update 130 | - patch 131 | - apiGroups: 132 | - storage.k8s.io 133 | resources: 134 | - volumeattachments/status 135 | verbs: 136 | - update 137 | - patch 138 | - apiGroups: 139 | - snapshot.storage.k8s.io 140 | resources: 141 | - volumesnapshots 142 | - volumesnapshotclasses 143 | verbs: 144 | - get 145 | - list 146 | - watch 147 | - update 148 | - patch 149 | - apiGroups: 150 | - snapshot.storage.k8s.io 151 | resources: 152 | - volumesnapshotclasses 153 | verbs: 154 | - create 155 | - apiGroups: 156 | - snapshot.storage.k8s.io 157 | resources: 158 | - volumesnapshots/status 159 | - volumesnapshotcontents/status 160 | verbs: 161 | - update 162 | - patch 163 | - apiGroups: 164 | - snapshot.storage.k8s.io 165 | resources: 166 | - volumesnapshotcontents 167 | verbs: 168 | - get 169 | - list 170 | - watch 171 | - create 172 | - delete 173 | - update 174 | - patch 175 | - apiGroups: 176 | - csi.storage.k8s.io 177 | resources: 178 | - csidrivers 179 | - csinodeinfos 180 | verbs: 181 | - get 182 | - list 183 | - watch 184 | - create 185 | - delete 186 | - update 187 | - patch 188 | - apiGroups: 189 | - storage.k8s.io 190 | resources: 191 | - csidrivers 192 | - csinodes 193 | verbs: 194 | - get 195 | - list 196 | - watch 197 | - create 198 | - delete 199 | - update 200 | - patch 201 | - apiGroups: 202 | - apiextensions.k8s.io 203 | resources: 204 | - customresourcedefinitions 205 | verbs: 206 | - get 207 | - list 208 | - watch 209 | - create 210 | - delete 211 | - update 212 | - patch 213 | - apiGroups: 214 | - trident.qnap.io 215 | resources: 216 | - tridentversions 217 | - tridentbackends 218 | - tridentstorageclasses 219 | - tridentvolumes 220 | - tridentvolumepublications 221 | - tridentvolumereferences 222 | - tridentnodes 223 | - tridenttransactions 224 | - tridentsnapshots 225 | - tridentbackendconfigs 226 | - tridentbackendconfigs/status 227 | - tridentmirrorrelationships 228 | - tridentmirrorrelationships/status 229 | - tridentactionmirrorupdates 230 | - tridentactionmirrorupdates/status 231 | - tridentsnapshotinfos 232 | - tridentsnapshotinfos/status 233 | - tridentactionsnapshotrestores 234 | - tridentactionsnapshotrestores/status 235 | - tridentprovisioners # Required for Tprov 236 | - tridentprovisioners/status # Required to update Tprov's status section 237 | - tridentorchestrators # Required for Torc 238 | - tridentorchestrators/status # Required to update Torc's status section 239 | - tridentconfigurators # Required for tconf 240 | - tridentconfigurators/status # Required to update tconf's status section 241 | verbs: 242 | - get 243 | - list 244 | - watch 245 | - create 246 | - delete 247 | - update 248 | - patch 249 | - apiGroups: 250 | - policy 251 | resources: 252 | - podsecuritypolicies 253 | verbs: 254 | - use 255 | resourceNames: 256 | - tridentpods 257 | # Now Operator specific permissions 258 | - apiGroups: 259 | - "" 260 | resources: 261 | - namespaces 262 | verbs: 263 | - create 264 | - patch 265 | - apiGroups: 266 | - apps 267 | resources: 268 | - deployments 269 | - daemonsets 270 | - statefulsets 271 | verbs: 272 | - get 273 | - list 274 | - watch 275 | - create 276 | - apiGroups: 277 | - apps 278 | resources: 279 | - deployments 280 | - statefulsets 281 | verbs: 282 | - delete 283 | - update 284 | - patch 285 | resourceNames: 286 | - trident 287 | - trident-csi 288 | - trident-controller 289 | - apiGroups: 290 | - apps 291 | resources: 292 | - daemonsets 293 | verbs: 294 | - delete 295 | - update 296 | - patch 297 | resourceNames: 298 | - trident 299 | - trident-csi 300 | - trident-csi-windows 301 | - trident-node-linux 302 | - trident-node-windows 303 | - apiGroups: 304 | - "" 305 | resources: 306 | - pods/exec 307 | - services 308 | - serviceaccounts 309 | verbs: 310 | - get 311 | - list 312 | - create 313 | - apiGroups: 314 | - "" 315 | resources: 316 | - pods/exec 317 | - services 318 | verbs: 319 | - delete 320 | - update 321 | - patch 322 | resourceNames: 323 | - trident-csi 324 | - trident 325 | - apiGroups: 326 | - "" 327 | resources: 328 | - serviceaccounts 329 | verbs: 330 | - delete 331 | - update 332 | - patch 333 | resourceNames: 334 | - trident-controller 335 | - trident-node-linux 336 | - trident-node-windows 337 | - trident-csi 338 | - trident 339 | - apiGroups: 340 | - authorization.openshift.io 341 | - rbac.authorization.k8s.io 342 | resources: 343 | - roles 344 | - rolebindings 345 | - clusterroles 346 | - clusterrolebindings 347 | verbs: 348 | - list 349 | - create 350 | - apiGroups: 351 | - authorization.openshift.io 352 | - rbac.authorization.k8s.io 353 | resources: 354 | - roles 355 | - rolebindings 356 | - clusterroles 357 | - clusterrolebindings 358 | verbs: 359 | - delete 360 | - update 361 | - patch 362 | resourceNames: 363 | - trident-controller 364 | - trident-node-linux 365 | - trident-node-windows 366 | - trident-csi 367 | - trident 368 | - apiGroups: 369 | - policy 370 | resources: 371 | - podsecuritypolicies 372 | verbs: 373 | - list 374 | - create 375 | - apiGroups: 376 | - policy 377 | resources: 378 | - podsecuritypolicies 379 | resourceNames: 380 | - tridentpods 381 | verbs: 382 | - delete 383 | - update 384 | - patch 385 | - apiGroups: 386 | - security.openshift.io 387 | resources: 388 | - securitycontextconstraints 389 | verbs: 390 | - get 391 | - list 392 | - create 393 | - apiGroups: 394 | - security.openshift.io 395 | resources: 396 | - securitycontextconstraints 397 | resourceNames: 398 | - trident-controller 399 | - trident-node-linux 400 | - trident-node-windows 401 | - trident 402 | verbs: 403 | - delete 404 | - update 405 | - patch 406 | - apiGroups: 407 | - policy 408 | resources: 409 | - podsecuritypolicies 410 | verbs: 411 | - use 412 | resourceNames: 413 | - trident-controller 414 | - trident-node-linux 415 | - trident-node-windows 416 | - tridentoperatorpods 417 | # Now Qnap Operator 418 | - apiGroups: 419 | - trident.qnap.com 420 | resources: 421 | - qnapvolumes 422 | verbs: 423 | - create 424 | - delete 425 | - get 426 | - list 427 | - patch 428 | - update 429 | - watch 430 | - apiGroups: 431 | - trident.qnap.com 432 | resources: 433 | - qnapvolumes/finalizers 434 | verbs: 435 | - update 436 | - apiGroups: 437 | - trident.qnap.com 438 | resources: 439 | - qnapvolumes/status 440 | verbs: 441 | - get 442 | - patch 443 | - update 444 | - apiGroups: 445 | - trident.qnap.com 446 | resources: 447 | - qpools 448 | verbs: 449 | - create 450 | - delete 451 | - get 452 | - list 453 | - patch 454 | - update 455 | - watch 456 | - apiGroups: 457 | - trident.qnap.com 458 | resources: 459 | - qpools/finalizers 460 | verbs: 461 | - update 462 | - apiGroups: 463 | - trident.qnap.com 464 | resources: 465 | - qpools/status 466 | verbs: 467 | - get 468 | - patch 469 | - update 470 | - apiGroups: 471 | - trident.qnap.com 472 | resources: 473 | - qsnapshots 474 | verbs: 475 | - create 476 | - delete 477 | - get 478 | - list 479 | - patch 480 | - update 481 | - watch 482 | - apiGroups: 483 | - trident.qnap.com 484 | resources: 485 | - qsnapshots/finalizers 486 | verbs: 487 | - update 488 | - apiGroups: 489 | - trident.qnap.com 490 | resources: 491 | - qsnapshots/status 492 | verbs: 493 | - get 494 | - patch 495 | - update 496 | --- 497 | apiVersion: rbac.authorization.k8s.io/v1 498 | kind: ClusterRoleBinding 499 | metadata: 500 | labels: 501 | app: operator.trident.qnap.io 502 | name: trident-operator 503 | roleRef: 504 | apiGroup: rbac.authorization.k8s.io 505 | kind: ClusterRole 506 | name: trident-operator 507 | subjects: 508 | - kind: ServiceAccount 509 | name: trident-operator 510 | namespace: trident 511 | --- 512 | apiVersion: apps/v1 513 | kind: Deployment 514 | metadata: 515 | labels: 516 | app: operator.trident.qnap.io 517 | name: trident-operator 518 | namespace: trident 519 | spec: 520 | replicas: 1 521 | strategy: 522 | type: Recreate 523 | selector: 524 | matchLabels: 525 | app: operator.trident.qnap.io 526 | name: trident-operator 527 | template: 528 | metadata: 529 | labels: 530 | app: operator.trident.qnap.io 531 | name: trident-operator 532 | spec: 533 | containers: 534 | - command: 535 | - /trident-operator 536 | - --log-level=debug 537 | - --qts-cgi-image=qnapsystem/qnap-csi-backend-qts-sidecar:v1.5.0 538 | env: 539 | - name: POD_NAME 540 | valueFrom: 541 | fieldRef: 542 | fieldPath: metadata.name 543 | - name: OPERATOR_NAME 544 | value: trident-operator 545 | image: qnapsystem/qnap-csi-operator:v1.5.0 546 | imagePullPolicy: IfNotPresent 547 | name: trident-operator 548 | resources: 549 | requests: 550 | cpu: "10m" 551 | memory: "40Mi" 552 | limits: 553 | cpu: "20m" 554 | memory: "80Mi" 555 | securityContext: 556 | allowPrivilegeEscalation: false 557 | seccompProfile: 558 | type: RuntimeDefault 559 | capabilities: 560 | drop: ["ALL"] 561 | affinity: 562 | nodeAffinity: 563 | requiredDuringSchedulingIgnoredDuringExecution: 564 | nodeSelectorTerms: 565 | - matchExpressions: 566 | - key: kubernetes.io/arch 567 | operator: In 568 | values: 569 | - arm64 570 | - amd64 571 | - key: kubernetes.io/os 572 | operator: In 573 | values: 574 | - linux 575 | serviceAccountName: trident-operator 576 | -------------------------------------------------------------------------------- /Deploy/Trident/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - namespace.yaml 6 | - bundle.yaml 7 | - tridentorchestrator.yaml 8 | -------------------------------------------------------------------------------- /Deploy/Trident/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: trident 5 | -------------------------------------------------------------------------------- /Deploy/Trident/tridentorchestrator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: trident.qnap.io/v1 2 | kind: TridentOrchestrator 3 | metadata: 4 | name: trident 5 | spec: 6 | debug: true 7 | namespace: trident 8 | tridentImage: qnapsystem/qnap-csi:v1.5.0 -------------------------------------------------------------------------------- /Deploy/crds/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - tridentorchestrator_crd.yaml -------------------------------------------------------------------------------- /Deploy/crds/tridentorchestrator_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: tridentorchestrators.trident.qnap.io 5 | spec: 6 | group: trident.qnap.io 7 | versions: 8 | - name: v1 9 | served: true 10 | storage: true 11 | schema: 12 | openAPIV3Schema: 13 | type: object 14 | x-kubernetes-preserve-unknown-fields: true 15 | subresources: 16 | status: {} 17 | names: 18 | kind: TridentOrchestrator 19 | listKind: TridentOrchestratorList 20 | plural: tridentorchestrators 21 | singular: tridentorchestrator 22 | shortNames: 23 | - torc 24 | - torchestrator 25 | scope: Cluster 26 | -------------------------------------------------------------------------------- /Helm/trident/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Helm/trident/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: trident 3 | description: A Helm chart for deploying Trident CSI Plugin using Trident Operator 4 | type: application 5 | version: 2.0.0 6 | kubeVersion: ">= 1.24.0 <= 1.30" 7 | appVersion: 1.3.0 8 | -------------------------------------------------------------------------------- /Helm/trident/crds/tridentorchestrator_crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: tridentorchestrators.trident.qnap.io 5 | spec: 6 | group: trident.qnap.io 7 | versions: 8 | - name: v1 9 | served: true 10 | storage: true 11 | schema: 12 | openAPIV3Schema: 13 | type: object 14 | x-kubernetes-preserve-unknown-fields: true 15 | subresources: 16 | status: {} 17 | names: 18 | kind: TridentOrchestrator 19 | listKind: TridentOrchestratorList 20 | plural: tridentorchestrators 21 | singular: tridentorchestrator 22 | shortNames: 23 | - torc 24 | - torchestrator 25 | scope: Cluster 26 | -------------------------------------------------------------------------------- /Helm/trident/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Thank you for installing {{ .Chart.Name }}, which will deploy and manage Trident CSI storage provisioner for Kubernetes. 2 | 3 | Your release is named '{{ .Release.Name }}' and is installed into the '{{ .Release.Namespace }}' namespace. 4 | Please note that there must be only one instance of Trident (and trident-operator) in a Kubernetes cluster. 5 | 6 | To configure Trident to manage storage resources, you will need a copy of tridentctl, which is 7 | available in pre-packaged Trident releases. You may find all Trident releases and source code 8 | online at {{ .Chart.Home }}. 9 | 10 | To learn more about the release, try: 11 | 12 | $ helm status {{ .Release.Name }} -n trident 13 | $ helm get all {{ .Release.Name }} -n trident 14 | 15 | To uninstall, try: 16 | $ helm delete {{ .Release.Name }} -n trident 17 | 18 | 19 | -------------------------------------------------------------------------------- /Helm/trident/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "qnap-trident.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "qnap-trident.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "qnap-trident.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "qnap-trident.labels" -}} 37 | helm.sh/chart: {{ include "qnap-trident.chart" . }} 38 | {{ include "qnap-trident.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "qnap-trident.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "qnap-trident.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | -------------------------------------------------------------------------------- /Helm/trident/templates/bundle.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app: operator.trident.qnap.io 6 | name: trident-operator 7 | namespace: {{ .Release.Namespace }} 8 | --- 9 | apiVersion: rbac.authorization.k8s.io/v1 10 | kind: ClusterRole 11 | metadata: 12 | creationTimestamp: null 13 | labels: 14 | app: operator.trident.qnap.io 15 | name: trident-operator 16 | rules: 17 | # Permissions same as Trident 18 | - apiGroups: 19 | - "" 20 | resources: 21 | - namespaces 22 | verbs: 23 | - get 24 | - list 25 | - apiGroups: 26 | - "" 27 | resources: 28 | - persistentvolumes 29 | - persistentvolumeclaims 30 | verbs: 31 | - get 32 | - list 33 | - watch 34 | - create 35 | - delete 36 | - update 37 | - patch 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - persistentvolumeclaims/status 42 | verbs: 43 | - update 44 | - patch 45 | - apiGroups: 46 | - storage.k8s.io 47 | resources: 48 | - storageclasses 49 | verbs: 50 | - get 51 | - list 52 | - watch 53 | - create 54 | - delete 55 | - update 56 | - patch 57 | - apiGroups: 58 | - "" 59 | resources: 60 | - events 61 | verbs: 62 | - get 63 | - list 64 | - watch 65 | - create 66 | - update 67 | - patch 68 | - apiGroups: 69 | - "" 70 | resources: 71 | - secrets 72 | verbs: 73 | - get 74 | - list 75 | - watch 76 | - create 77 | - delete 78 | - update 79 | - patch 80 | - apiGroups: 81 | - "" 82 | resources: 83 | - resourcequotas 84 | verbs: 85 | - get 86 | - list 87 | - watch 88 | - create 89 | - delete 90 | - update 91 | - patch 92 | - apiGroups: 93 | - "" 94 | resources: 95 | - pods 96 | verbs: 97 | - get 98 | - list 99 | - watch 100 | - create 101 | - delete 102 | - update 103 | - patch 104 | - apiGroups: 105 | - "" 106 | resources: 107 | - pods/log 108 | verbs: 109 | - get 110 | - list 111 | - watch 112 | - apiGroups: 113 | - "" 114 | resources: 115 | - nodes 116 | verbs: 117 | - get 118 | - list 119 | - watch 120 | - update 121 | - apiGroups: 122 | - storage.k8s.io 123 | resources: 124 | - volumeattachments 125 | verbs: 126 | - get 127 | - list 128 | - watch 129 | - update 130 | - patch 131 | - apiGroups: 132 | - storage.k8s.io 133 | resources: 134 | - volumeattachments/status 135 | verbs: 136 | - update 137 | - patch 138 | - apiGroups: 139 | - snapshot.storage.k8s.io 140 | resources: 141 | - volumesnapshots 142 | - volumesnapshotclasses 143 | verbs: 144 | - get 145 | - list 146 | - watch 147 | - update 148 | - patch 149 | - apiGroups: 150 | - snapshot.storage.k8s.io 151 | resources: 152 | - volumesnapshotclasses 153 | verbs: 154 | - create 155 | - apiGroups: 156 | - snapshot.storage.k8s.io 157 | resources: 158 | - volumesnapshots/status 159 | - volumesnapshotcontents/status 160 | verbs: 161 | - update 162 | - patch 163 | - apiGroups: 164 | - snapshot.storage.k8s.io 165 | resources: 166 | - volumesnapshotcontents 167 | verbs: 168 | - get 169 | - list 170 | - watch 171 | - create 172 | - delete 173 | - update 174 | - patch 175 | - apiGroups: 176 | - csi.storage.k8s.io 177 | resources: 178 | - csidrivers 179 | - csinodeinfos 180 | verbs: 181 | - get 182 | - list 183 | - watch 184 | - create 185 | - delete 186 | - update 187 | - patch 188 | - apiGroups: 189 | - storage.k8s.io 190 | resources: 191 | - csidrivers 192 | - csinodes 193 | verbs: 194 | - get 195 | - list 196 | - watch 197 | - create 198 | - delete 199 | - update 200 | - patch 201 | - apiGroups: 202 | - apiextensions.k8s.io 203 | resources: 204 | - customresourcedefinitions 205 | verbs: 206 | - get 207 | - list 208 | - watch 209 | - create 210 | - delete 211 | - update 212 | - patch 213 | - apiGroups: 214 | - trident.qnap.io 215 | resources: 216 | - tridentversions 217 | - tridentbackends 218 | - tridentstorageclasses 219 | - tridentvolumes 220 | - tridentvolumepublications 221 | - tridentvolumereferences 222 | - tridentnodes 223 | - tridenttransactions 224 | - tridentsnapshots 225 | - tridentbackendconfigs 226 | - tridentbackendconfigs/status 227 | - tridentmirrorrelationships 228 | - tridentmirrorrelationships/status 229 | - tridentactionmirrorupdates 230 | - tridentactionmirrorupdates/status 231 | - tridentsnapshotinfos 232 | - tridentsnapshotinfos/status 233 | - tridentactionsnapshotrestores 234 | - tridentactionsnapshotrestores/status 235 | - tridentprovisioners # Required for Tprov 236 | - tridentprovisioners/status # Required to update Tprov's status section 237 | - tridentorchestrators # Required for Torc 238 | - tridentorchestrators/status # Required to update Torc's status section 239 | - tridentconfigurators # Required for tconf 240 | - tridentconfigurators/status # Required to update tconf's status section 241 | verbs: 242 | - get 243 | - list 244 | - watch 245 | - create 246 | - delete 247 | - update 248 | - patch 249 | - apiGroups: 250 | - policy 251 | resources: 252 | - podsecuritypolicies 253 | verbs: 254 | - use 255 | resourceNames: 256 | - tridentpods 257 | # Now Operator specific permissions 258 | - apiGroups: 259 | - "" 260 | resources: 261 | - namespaces 262 | verbs: 263 | - create 264 | - patch 265 | - apiGroups: 266 | - apps 267 | resources: 268 | - deployments 269 | - daemonsets 270 | - statefulsets 271 | verbs: 272 | - get 273 | - list 274 | - watch 275 | - create 276 | - apiGroups: 277 | - apps 278 | resources: 279 | - deployments 280 | - statefulsets 281 | verbs: 282 | - delete 283 | - update 284 | - patch 285 | resourceNames: 286 | - trident 287 | - trident-csi 288 | - trident-controller 289 | - apiGroups: 290 | - apps 291 | resources: 292 | - daemonsets 293 | verbs: 294 | - delete 295 | - update 296 | - patch 297 | resourceNames: 298 | - trident 299 | - trident-csi 300 | - trident-csi-windows 301 | - trident-node-linux 302 | - trident-node-windows 303 | - apiGroups: 304 | - "" 305 | resources: 306 | - pods/exec 307 | - services 308 | - serviceaccounts 309 | verbs: 310 | - get 311 | - list 312 | - create 313 | - apiGroups: 314 | - "" 315 | resources: 316 | - pods/exec 317 | - services 318 | verbs: 319 | - delete 320 | - update 321 | - patch 322 | resourceNames: 323 | - trident-csi 324 | - trident 325 | - apiGroups: 326 | - "" 327 | resources: 328 | - serviceaccounts 329 | verbs: 330 | - delete 331 | - update 332 | - patch 333 | resourceNames: 334 | - trident-controller 335 | - trident-node-linux 336 | - trident-node-windows 337 | - trident-csi 338 | - trident 339 | - apiGroups: 340 | - authorization.openshift.io 341 | - rbac.authorization.k8s.io 342 | resources: 343 | - roles 344 | - rolebindings 345 | - clusterroles 346 | - clusterrolebindings 347 | verbs: 348 | - list 349 | - create 350 | - apiGroups: 351 | - authorization.openshift.io 352 | - rbac.authorization.k8s.io 353 | resources: 354 | - roles 355 | - rolebindings 356 | - clusterroles 357 | - clusterrolebindings 358 | verbs: 359 | - delete 360 | - update 361 | - patch 362 | resourceNames: 363 | - trident-controller 364 | - trident-node-linux 365 | - trident-node-windows 366 | - trident-csi 367 | - trident 368 | - apiGroups: 369 | - policy 370 | resources: 371 | - podsecuritypolicies 372 | verbs: 373 | - list 374 | - create 375 | - apiGroups: 376 | - policy 377 | resources: 378 | - podsecuritypolicies 379 | resourceNames: 380 | - tridentpods 381 | verbs: 382 | - delete 383 | - update 384 | - patch 385 | - apiGroups: 386 | - security.openshift.io 387 | resources: 388 | - securitycontextconstraints 389 | verbs: 390 | - get 391 | - list 392 | - create 393 | - apiGroups: 394 | - security.openshift.io 395 | resources: 396 | - securitycontextconstraints 397 | resourceNames: 398 | - trident-controller 399 | - trident-node-linux 400 | - trident-node-windows 401 | - trident 402 | verbs: 403 | - delete 404 | - update 405 | - patch 406 | - apiGroups: 407 | - policy 408 | resources: 409 | - podsecuritypolicies 410 | verbs: 411 | - use 412 | resourceNames: 413 | - trident-controller 414 | - trident-node-linux 415 | - trident-node-windows 416 | - tridentoperatorpods 417 | # Now Qnap Operator 418 | - apiGroups: 419 | - trident.qnap.com 420 | resources: 421 | - qnapvolumes 422 | verbs: 423 | - create 424 | - delete 425 | - get 426 | - list 427 | - patch 428 | - update 429 | - watch 430 | - apiGroups: 431 | - trident.qnap.com 432 | resources: 433 | - qnapvolumes/finalizers 434 | verbs: 435 | - update 436 | - apiGroups: 437 | - trident.qnap.com 438 | resources: 439 | - qnapvolumes/status 440 | verbs: 441 | - get 442 | - patch 443 | - update 444 | - apiGroups: 445 | - trident.qnap.com 446 | resources: 447 | - qpools 448 | verbs: 449 | - create 450 | - delete 451 | - get 452 | - list 453 | - patch 454 | - update 455 | - watch 456 | - apiGroups: 457 | - trident.qnap.com 458 | resources: 459 | - qpools/finalizers 460 | verbs: 461 | - update 462 | - apiGroups: 463 | - trident.qnap.com 464 | resources: 465 | - qpools/status 466 | verbs: 467 | - get 468 | - patch 469 | - update 470 | - apiGroups: 471 | - trident.qnap.com 472 | resources: 473 | - qsnapshots 474 | verbs: 475 | - create 476 | - delete 477 | - get 478 | - list 479 | - patch 480 | - update 481 | - watch 482 | - apiGroups: 483 | - trident.qnap.com 484 | resources: 485 | - qsnapshots/finalizers 486 | verbs: 487 | - update 488 | - apiGroups: 489 | - trident.qnap.com 490 | resources: 491 | - qsnapshots/status 492 | verbs: 493 | - get 494 | - patch 495 | - update 496 | --- 497 | apiVersion: rbac.authorization.k8s.io/v1 498 | kind: ClusterRoleBinding 499 | metadata: 500 | labels: 501 | app: operator.trident.qnap.io 502 | name: trident-operator 503 | roleRef: 504 | apiGroup: rbac.authorization.k8s.io 505 | kind: ClusterRole 506 | name: trident-operator 507 | subjects: 508 | - kind: ServiceAccount 509 | name: trident-operator 510 | namespace: {{ .Release.Namespace }} 511 | --- 512 | apiVersion: apps/v1 513 | kind: Deployment 514 | metadata: 515 | labels: 516 | app: operator.trident.qnap.io 517 | name: trident-operator 518 | namespace: {{ .Release.Namespace }} 519 | spec: 520 | replicas: 1 521 | strategy: 522 | type: Recreate 523 | selector: 524 | matchLabels: 525 | app: operator.trident.qnap.io 526 | name: trident-operator 527 | template: 528 | metadata: 529 | labels: 530 | app: operator.trident.qnap.io 531 | name: trident-operator 532 | spec: 533 | containers: 534 | - command: 535 | - /trident-operator 536 | - --log-level={{ .Values.tridentOperator.logLevel }} 537 | - --qts-cgi-image={{ .Values.tridentOperator.cgiServerImage }} 538 | env: 539 | - name: POD_NAME 540 | valueFrom: 541 | fieldRef: 542 | fieldPath: metadata.name 543 | - name: OPERATOR_NAME 544 | value: trident-operator 545 | image: {{ .Values.tridentOperator.image }} 546 | imagePullPolicy: {{ .Values.tridentOperator.imagePullPolicy }} 547 | name: trident-operator 548 | resources: 549 | requests: 550 | cpu: "10m" 551 | memory: "40Mi" 552 | limits: 553 | cpu: "20m" 554 | memory: "80Mi" 555 | securityContext: 556 | allowPrivilegeEscalation: false 557 | seccompProfile: 558 | type: RuntimeDefault 559 | capabilities: 560 | drop: ["ALL"] 561 | affinity: 562 | nodeAffinity: 563 | requiredDuringSchedulingIgnoredDuringExecution: 564 | nodeSelectorTerms: 565 | - matchExpressions: 566 | - key: kubernetes.io/arch 567 | operator: In 568 | values: 569 | - arm64 570 | - amd64 571 | - key: kubernetes.io/os 572 | operator: In 573 | values: 574 | - linux 575 | serviceAccountName: trident-operator 576 | -------------------------------------------------------------------------------- /Helm/trident/templates/tridentorchestrator.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: trident.qnap.io/v1 2 | kind: TridentOrchestrator 3 | metadata: 4 | name: trident 5 | spec: 6 | debug: {{ .Values.tridentOrchestrator.debug }} 7 | namespace: {{ .Release.Namespace }} 8 | tridentImage: {{ .Values.tridentOrchestrator.image}} 9 | -------------------------------------------------------------------------------- /Helm/trident/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for qnap-trident. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | tridentOperator: 8 | image: qnapsystem/qnap-csi-operator:v1.5.0 9 | cgiServerImage : qnapsystem/qnap-csi-backend-qts-sidecar:v1.5.0 10 | imagePullPolicy: IfNotPresent 11 | logLevel: debug 12 | 13 | tridentOrchestrator: 14 | image: qnapsystem/qnap-csi:v1.5.0 15 | debug: true -------------------------------------------------------------------------------- /License: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Samples/Backend/backend-sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "storageDriverName": "qnap-iscsi", 4 | "backendName": "qts", 5 | "storageAddress": "0.0.0.0", 6 | "username": "user", 7 | "password": "0000", 8 | "networkInterfaces": ["Adapter1"], 9 | "debugTraceFlags": {"method": true}, 10 | "storage": [ 11 | { 12 | "labels": {"performance": "performance1"}, 13 | "features":{ 14 | "tiering": "Enable" 15 | }, 16 | "serviceLevel": "pool1" 17 | }, 18 | { 19 | "labels": {"performance": "performance2"}, 20 | "features":{ 21 | "tiering": "Enable", 22 | "ssdCache": "true", 23 | "raidLevel": "1" 24 | }, 25 | "serviceLevel": "pool2" 26 | }, 27 | ] 28 | } -------------------------------------------------------------------------------- /Samples/Backend/backend-sample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: backend-qts-secret # Required. Name your secret. 5 | namespace: trident 6 | type: Opaque 7 | stringData: 8 | username: user # Required. Your NAS username. 9 | password: 0000 # Required. Your NAS password. 10 | storageAddress: 0.0.0.0 # Required. Your NAS IP address. 11 | --- 12 | apiVersion: trident.qnap.io/v1 13 | kind: TridentBackendConfig 14 | metadata: 15 | name: backend-qts # Required. Name your backend in Kubernetes. 16 | namespace: trident 17 | spec: 18 | version: 1 19 | storageDriverName: qnap-nas #Required. Support 'qnap-nas'(latest) or 'qnap-iscsi' 20 | backendName: qts # Required. Name your backend in QNAP CSI. 21 | networkInterfaces: ["Adapter1"] # Optional. Your adapter name or leave it empty. 22 | credentials: 23 | name: backend-qts-secret # Required. Enter the secret name set in metadata.name. 24 | debugTraceFlags: 25 | method: true 26 | storage: # Required. Define one or more virtual pools. 27 | - serviceLevel: pool1 # Required. Name your virtual pool. 28 | labels: # Required. Define custom labels for your virtual pool. 29 | performance: performance1 30 | features: # Optional. Define features for your virtual pool. 31 | tiering: Enable 32 | - serviceLevel: pool2 33 | labels: 34 | performance: performance2 35 | features: 36 | tiering: Enable 37 | ssdCache: "true" 38 | raidLevel: "1" -------------------------------------------------------------------------------- /Samples/Secret/smb_user_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: qts-csi-smb #Required. Name your secert for Samba. 5 | namespace: trident 6 | type: Opaque 7 | stringData: 8 | username: user1 #Required. The valid Samba username on the NAS. 9 | password: 0000 #Required. The valid Samba password on the NAS. -------------------------------------------------------------------------------- /Samples/Snapshot/VolumeSnapshot.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: snapshot.storage.k8s.io/v1 2 | kind: VolumeSnapshot 3 | metadata: 4 | name: pvc-snapshot 5 | spec: 6 | volumeSnapshotClassName: trident-snapshotclass 7 | source: 8 | persistentVolumeClaimName: pvc-sample -------------------------------------------------------------------------------- /Samples/Snapshot/VolumeSnapshotClass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: snapshot.storage.k8s.io/v1 2 | kind: VolumeSnapshotClass 3 | metadata: 4 | name: trident-snapshotclass 5 | driver: csi.trident.qnap.io 6 | deletionPolicy: Delete 7 | -------------------------------------------------------------------------------- /Samples/StorageClass/sc_iscsi_sample.yaml.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: storageclass1 # Required. Name your storageclass. 5 | provisioner: csi.trident.qnap.io 6 | parameters: 7 | selector: "performance=performance1" # Required. Corresponds to the labels in the virtual pool. 8 | fsType: "ext4" # Optional. You can choose to enter ext4 (default), xfs, or ext3. 9 | allowVolumeExpansion: true -------------------------------------------------------------------------------- /Samples/StorageClass/sc_smb_sample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: storageclass1 # Required. Name your storageclass. 5 | provisioner: csi.trident.qnap.io 6 | parameters: 7 | selector: "performance=performance1" # Required. Corresponds to the labels in the virtual pool. 8 | trident.qnap.io/fileProtocol: "smb" 9 | csi.storage.k8s.io/node-stage-secret-name: "qts-csi-smb" # Required. It must match the metadata.name in the Secret file. 10 | csi.storage.k8s.io/node-stage-secret-namespace: "trident" # Required. It must match the metadata.namespace in the Secret file. 11 | allowVolumeExpansion: true -------------------------------------------------------------------------------- /Samples/Volumes/clone/pvc-clone-file.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-from-clone-file 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 30Gi 11 | dataSource: 12 | kind: PersistentVolumeClaim 13 | name: pvc-file 14 | storageClassName: qts-smb 15 | 16 | -------------------------------------------------------------------------------- /Samples/Volumes/clone/pvc-clone-from-snap-file.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-from-clone-snap-file 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 10Gi 11 | dataSource: 12 | name: pvc-snapshot-file 13 | kind: VolumeSnapshot 14 | apiGroup: snapshot.storage.k8s.io 15 | storageClassName: qts-smb 16 | 17 | -------------------------------------------------------------------------------- /Samples/Volumes/clone/pvc-clone.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-from-clone-blk 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | resources: 9 | requests: 10 | storage: 30Gi 11 | dataSource: 12 | kind: PersistentVolumeClaim 13 | name: pvc-block 14 | storageClassName: premium 15 | -------------------------------------------------------------------------------- /Samples/Volumes/clone/pvc-snap.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-from-snap-blk 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce 8 | resources: 9 | requests: 10 | storage: 10Gi 11 | dataSource: 12 | name: pvc-snapshot-premium 13 | kind: VolumeSnapshot 14 | apiGroup: snapshot.storage.k8s.io 15 | storageClassName: premium -------------------------------------------------------------------------------- /Samples/Volumes/import/pvc-import-file.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-import-file-test 5 | namespace: default 6 | annotations: 7 | trident.qnap.io/importOriginalName: "bbb" 8 | trident.qnap.io/importBackendName: "hero" 9 | spec: 10 | accessModes: 11 | - ReadWriteMany 12 | resources: 13 | requests: 14 | storage: 10Gi #9564Mi #9.34Gi 15 | storageClassName: qts-smb 16 | -------------------------------------------------------------------------------- /Samples/Volumes/import/pvc-import.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-import-blk 5 | namespace: default 6 | annotations: 7 | trident.qnap.io/importOriginalName: "LUN_0" 8 | trident.qnap.io/importBackendName: "hero" 9 | spec: 10 | accessModes: 11 | - ReadWriteOnce 12 | resources: 13 | requests: 14 | storage: 10Gi 15 | storageClassName: premium 16 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-any.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-any-1 5 | annotations: 6 | # thin allocate & threshold is customized 7 | trident.qnap.io/Threshold: "90" 8 | trident.qnap.io/ThinAllocate: "true" 9 | spec: 10 | accessModes: 11 | - ReadWriteOnce 12 | resources: 13 | requests: 14 | storage: 10Gi 15 | storageClassName: any 16 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-backend.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-qts-david 5 | annotations: 6 | trident.qnap.io/threshold: "90" 7 | trident.qnap.io/ThinAllocate: "true" 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce 11 | resources: 12 | requests: 13 | storage: 5Gi 14 | storageClassName: qts-david 15 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-block.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-block-basic 5 | annotations: 6 | # thin allocate is customized 7 | trident.qnap.io/Threshold: "77" 8 | trident.qnap.io/ThinAllocate: "true" 9 | 10 | # QuTS-hero features 11 | # trident.qnap.io/Deduplication: "true" 12 | # trident.qnap.io/Compression: "true" 13 | # trident.qnap.io/FastClone: "true" 14 | spec: 15 | accessModes: 16 | - ReadWriteOnce 17 | resources: 18 | requests: 19 | storage: 10Gi 20 | storageClassName: basic 21 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-file.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-file-2 5 | annotations: 6 | # thin allocate is customized 7 | trident.qnap.io/Threshold: "66" 8 | trident.qnap.io/ThinAllocate: "true" 9 | 10 | # QuTS-hero features 11 | #trident.qnap.io/Deduplication: "true" 12 | #trident.qnap.io/Compression: "true" 13 | #trident.qnap.io/FastClone: "true" 14 | spec: 15 | accessModes: 16 | - ReadWriteMany 17 | resources: 18 | requests: 19 | storage: 30Gi 20 | storageClassName: qts-smb 21 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-hero.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-premium-hero 5 | annotations: 6 | # thin allocate is customized 7 | trident.qnap.io/ThinAllocate: "false" 8 | 9 | # QuTS-hero features 10 | trident.qnap.io/Deduplication: "true" 11 | trident.qnap.io/Compression: "true" 12 | trident.qnap.io/FastClone: "true" 13 | spec: 14 | accessModes: 15 | - ReadWriteOnce 16 | resources: 17 | requests: 18 | storage: 5Gi 19 | storageClassName: premium 20 | -------------------------------------------------------------------------------- /Samples/Volumes/normal/pvc-raid.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-raid5 5 | annotations: 6 | # thin allocate & threshold is customized 7 | trident.qnap.io/threshold: "66" 8 | trident.qnap.io/ThinAllocate: "true" 9 | spec: 10 | accessModes: 11 | - ReadWriteOnce 12 | resources: 13 | requests: 14 | storage: 5Gi 15 | storageClassName: raid5 16 | -------------------------------------------------------------------------------- /Samples/Volumes/pvc-clone.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: pvc-from-clone 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce # iSCSI: ReadWriteOnce, Samba: ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 5Gi 11 | dataSource: 12 | kind: PersistentVolumeClaim 13 | name: pvc-sample 14 | storageClassName: storageclass1 15 | -------------------------------------------------------------------------------- /Samples/Volumes/pvc-from-snapshot.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-from-snap 5 | spec: 6 | accessModes: 7 | - ReadWriteOnce # iSCSI: ReadWriteOnce, Samba: ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 5Gi 11 | dataSource: 12 | name: pvc-snapshot 13 | kind: VolumeSnapshot 14 | apiGroup: snapshot.storage.k8s.io 15 | storageClassName: storageclass1 16 | -------------------------------------------------------------------------------- /Samples/Volumes/pvc-import.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc-import-file 5 | annotations: 6 | trident.qnap.io/importOriginalName: "shared-name" 7 | trident.qnap.io/importBackendName: "qts" 8 | spec: 9 | accessModes: 10 | - ReadWriteMany 11 | resources: 12 | requests: 13 | storage: 10Gi #The value entered should correspond to the actual or displayed size. 14 | storageClassName: storageclass1 15 | -------------------------------------------------------------------------------- /Samples/Volumes/pvc-sample.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: pvc1 5 | annotations: # Required. Define features for your volume. 6 | trident.qnap.io/threshold: "90" 7 | trident.qnap.io/ThinAllocate: "true" 8 | spec: 9 | accessModes: 10 | - ReadWriteOnce # Required. iSCSI: ReadWriteOnce, Samba: ReadWriteMany 11 | resources: 12 | requests: 13 | storage: 10Gi # Required. Specify your resource size. 14 | storageClassName: storageclass1 # Required. Corresponds to the StorageClass name. 15 | -------------------------------------------------------------------------------- /Samples/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: app-file 5 | spec: 6 | replicas: 1 7 | selector: 8 | matchLabels: 9 | app: demo-label 10 | template: 11 | metadata: 12 | labels: 13 | app: demo-label 14 | spec: 15 | containers: 16 | - name: demo-pod 17 | image: davidcheng0922/docker-demo 18 | ports: 19 | - containerPort: 80 20 | volumeMounts: 21 | - name: my-pvc 22 | mountPath: "/demo" 23 | volumes: 24 | - name: my-pvc 25 | persistentVolumeClaim: 26 | claimName: pvc-file 27 | -------------------------------------------------------------------------------- /VolumeSnapshot/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - snapshot.storage.k8s.io_volumesnapshotclasses.yaml 5 | - snapshot.storage.k8s.io_volumesnapshotcontents.yaml 6 | - snapshot.storage.k8s.io_volumesnapshots.yaml 7 | - rbac-snapshot-controller.yaml 8 | - setup-snapshot-controller.yaml 9 | -------------------------------------------------------------------------------- /VolumeSnapshot/rbac-snapshot-controller.yaml: -------------------------------------------------------------------------------- 1 | # RBAC file for the snapshot controller. 2 | # 3 | # The snapshot controller implements the control loop for CSI snapshot functionality. 4 | # It should be installed as part of the base Kubernetes distribution in an appropriate 5 | # namespace for components implementing base system functionality. For installing with 6 | # Vanilla Kubernetes, kube-system makes sense for the namespace. 7 | 8 | apiVersion: v1 9 | kind: ServiceAccount 10 | metadata: 11 | name: snapshot-controller 12 | namespace: kube-system 13 | 14 | --- 15 | kind: ClusterRole 16 | apiVersion: rbac.authorization.k8s.io/v1 17 | metadata: 18 | name: snapshot-controller-runner 19 | rules: 20 | - apiGroups: [""] 21 | resources: ["persistentvolumes"] 22 | verbs: ["get", "list", "watch"] 23 | - apiGroups: [""] 24 | resources: ["persistentvolumeclaims"] 25 | verbs: ["get", "list", "watch", "update"] 26 | - apiGroups: ["storage.k8s.io"] 27 | resources: ["storageclasses"] 28 | verbs: ["get", "list", "watch"] 29 | - apiGroups: [""] 30 | resources: ["events"] 31 | verbs: ["list", "watch", "create", "update", "patch"] 32 | - apiGroups: ["snapshot.storage.k8s.io"] 33 | resources: ["volumesnapshotclasses"] 34 | verbs: ["get", "list", "watch"] 35 | - apiGroups: ["snapshot.storage.k8s.io"] 36 | resources: ["volumesnapshotcontents"] 37 | verbs: ["create", "get", "list", "watch", "update", "delete", "patch"] 38 | - apiGroups: ["snapshot.storage.k8s.io"] 39 | resources: ["volumesnapshotcontents/status"] 40 | verbs: ["patch"] 41 | - apiGroups: ["snapshot.storage.k8s.io"] 42 | resources: ["volumesnapshots"] 43 | verbs: ["get", "list", "watch", "update", "patch"] 44 | - apiGroups: ["snapshot.storage.k8s.io"] 45 | resources: ["volumesnapshots/status"] 46 | verbs: ["update", "patch"] 47 | # Enable this RBAC rule only when using distributed snapshotting, i.e. when the enable-distributed-snapshotting flag is set to true 48 | # - apiGroups: [""] 49 | # resources: ["nodes"] 50 | # verbs: ["get", "list", "watch"] 51 | --- 52 | kind: ClusterRoleBinding 53 | apiVersion: rbac.authorization.k8s.io/v1 54 | metadata: 55 | name: snapshot-controller-role 56 | subjects: 57 | - kind: ServiceAccount 58 | name: snapshot-controller 59 | namespace: kube-system 60 | roleRef: 61 | kind: ClusterRole 62 | name: snapshot-controller-runner 63 | apiGroup: rbac.authorization.k8s.io 64 | 65 | --- 66 | kind: Role 67 | apiVersion: rbac.authorization.k8s.io/v1 68 | metadata: 69 | name: snapshot-controller-leaderelection 70 | namespace: kube-system 71 | rules: 72 | - apiGroups: ["coordination.k8s.io"] 73 | resources: ["leases"] 74 | verbs: ["get", "watch", "list", "delete", "update", "create"] 75 | 76 | --- 77 | kind: RoleBinding 78 | apiVersion: rbac.authorization.k8s.io/v1 79 | metadata: 80 | name: snapshot-controller-leaderelection 81 | namespace: kube-system 82 | subjects: 83 | - kind: ServiceAccount 84 | name: snapshot-controller 85 | roleRef: 86 | kind: Role 87 | name: snapshot-controller-leaderelection 88 | apiGroup: rbac.authorization.k8s.io 89 | -------------------------------------------------------------------------------- /VolumeSnapshot/setup-snapshot-controller.yaml: -------------------------------------------------------------------------------- 1 | # This YAML file shows how to deploy the snapshot controller 2 | 3 | # The snapshot controller implements the control loop for CSI snapshot functionality. 4 | # It should be installed as part of the base Kubernetes distribution in an appropriate 5 | # namespace for components implementing base system functionality. For installing with 6 | # Vanilla Kubernetes, kube-system makes sense for the namespace. 7 | 8 | --- 9 | kind: Deployment 10 | apiVersion: apps/v1 11 | metadata: 12 | name: snapshot-controller 13 | namespace: kube-system 14 | spec: 15 | replicas: 2 16 | selector: 17 | matchLabels: 18 | app: snapshot-controller 19 | # the snapshot controller won't be marked as ready if the v1 CRDs are unavailable 20 | # in #504 the snapshot-controller will exit after around 7.5 seconds if it 21 | # can't find the v1 CRDs so this value should be greater than that 22 | minReadySeconds: 15 23 | strategy: 24 | rollingUpdate: 25 | maxSurge: 0 26 | maxUnavailable: 1 27 | type: RollingUpdate 28 | template: 29 | metadata: 30 | labels: 31 | app: snapshot-controller 32 | spec: 33 | serviceAccount: snapshot-controller 34 | containers: 35 | - name: snapshot-controller 36 | image: gcr.io/k8s-staging-sig-storage/snapshot-controller:v5.0.0 37 | args: 38 | - "--v=5" 39 | - "--leader-election=true" 40 | imagePullPolicy: IfNotPresent 41 | -------------------------------------------------------------------------------- /VolumeSnapshot/snapshot.storage.k8s.io_volumesnapshotclasses.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.4.0 8 | api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" 9 | creationTimestamp: null 10 | name: volumesnapshotclasses.snapshot.storage.k8s.io 11 | spec: 12 | group: snapshot.storage.k8s.io 13 | names: 14 | kind: VolumeSnapshotClass 15 | listKind: VolumeSnapshotClassList 16 | plural: volumesnapshotclasses 17 | shortNames: 18 | - vsclass 19 | - vsclasses 20 | singular: volumesnapshotclass 21 | scope: Cluster 22 | versions: 23 | - additionalPrinterColumns: 24 | - jsonPath: .driver 25 | name: Driver 26 | type: string 27 | - description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. 28 | jsonPath: .deletionPolicy 29 | name: DeletionPolicy 30 | type: string 31 | - jsonPath: .metadata.creationTimestamp 32 | name: Age 33 | type: date 34 | name: v1 35 | schema: 36 | openAPIV3Schema: 37 | description: VolumeSnapshotClass specifies parameters that a underlying storage system uses when creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses are non-namespaced 38 | properties: 39 | apiVersion: 40 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 41 | type: string 42 | deletionPolicy: 43 | description: deletionPolicy determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. 44 | enum: 45 | - Delete 46 | - Retain 47 | type: string 48 | driver: 49 | description: driver is the name of the storage driver that handles this VolumeSnapshotClass. Required. 50 | type: string 51 | kind: 52 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 53 | type: string 54 | parameters: 55 | additionalProperties: 56 | type: string 57 | description: parameters is a key-value map with storage driver specific parameters for creating snapshots. These values are opaque to Kubernetes. 58 | type: object 59 | required: 60 | - deletionPolicy 61 | - driver 62 | type: object 63 | served: true 64 | storage: true 65 | subresources: {} 66 | - additionalPrinterColumns: 67 | - jsonPath: .driver 68 | name: Driver 69 | type: string 70 | - description: Determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. 71 | jsonPath: .deletionPolicy 72 | name: DeletionPolicy 73 | type: string 74 | - jsonPath: .metadata.creationTimestamp 75 | name: Age 76 | type: date 77 | name: v1beta1 78 | # This indicates the v1beta1 version of the custom resource is deprecated. 79 | # API requests to this version receive a warning in the server response. 80 | deprecated: true 81 | # This overrides the default warning returned to clients making v1beta1 API requests. 82 | deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshotClass is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotClass" 83 | schema: 84 | openAPIV3Schema: 85 | description: VolumeSnapshotClass specifies parameters that a underlying storage system uses when creating a volume snapshot. A specific VolumeSnapshotClass is used by specifying its name in a VolumeSnapshot object. VolumeSnapshotClasses are non-namespaced 86 | properties: 87 | apiVersion: 88 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 89 | type: string 90 | deletionPolicy: 91 | description: deletionPolicy determines whether a VolumeSnapshotContent created through the VolumeSnapshotClass should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. Required. 92 | enum: 93 | - Delete 94 | - Retain 95 | type: string 96 | driver: 97 | description: driver is the name of the storage driver that handles this VolumeSnapshotClass. Required. 98 | type: string 99 | kind: 100 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 101 | type: string 102 | parameters: 103 | additionalProperties: 104 | type: string 105 | description: parameters is a key-value map with storage driver specific parameters for creating snapshots. These values are opaque to Kubernetes. 106 | type: object 107 | required: 108 | - deletionPolicy 109 | - driver 110 | type: object 111 | served: true 112 | storage: false 113 | subresources: {} 114 | status: 115 | acceptedNames: 116 | kind: "" 117 | plural: "" 118 | conditions: [] 119 | storedVersions: [] 120 | -------------------------------------------------------------------------------- /VolumeSnapshot/snapshot.storage.k8s.io_volumesnapshotcontents.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.4.0 8 | api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" 9 | creationTimestamp: null 10 | name: volumesnapshotcontents.snapshot.storage.k8s.io 11 | spec: 12 | group: snapshot.storage.k8s.io 13 | names: 14 | kind: VolumeSnapshotContent 15 | listKind: VolumeSnapshotContentList 16 | plural: volumesnapshotcontents 17 | shortNames: 18 | - vsc 19 | - vscs 20 | singular: volumesnapshotcontent 21 | scope: Cluster 22 | versions: 23 | - additionalPrinterColumns: 24 | - description: Indicates if the snapshot is ready to be used to restore a volume. 25 | jsonPath: .status.readyToUse 26 | name: ReadyToUse 27 | type: boolean 28 | - description: Represents the complete size of the snapshot in bytes 29 | jsonPath: .status.restoreSize 30 | name: RestoreSize 31 | type: integer 32 | - description: Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. 33 | jsonPath: .spec.deletionPolicy 34 | name: DeletionPolicy 35 | type: string 36 | - description: Name of the CSI driver used to create the physical snapshot on the underlying storage system. 37 | jsonPath: .spec.driver 38 | name: Driver 39 | type: string 40 | - description: Name of the VolumeSnapshotClass to which this snapshot belongs. 41 | jsonPath: .spec.volumeSnapshotClassName 42 | name: VolumeSnapshotClass 43 | type: string 44 | - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. 45 | jsonPath: .spec.volumeSnapshotRef.name 46 | name: VolumeSnapshot 47 | type: string 48 | - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. 49 | jsonPath: .spec.volumeSnapshotRef.namespace 50 | name: VolumeSnapshotNamespace 51 | type: string 52 | - jsonPath: .metadata.creationTimestamp 53 | name: Age 54 | type: date 55 | name: v1 56 | schema: 57 | openAPIV3Schema: 58 | description: VolumeSnapshotContent represents the actual "on-disk" snapshot object in the underlying storage system 59 | properties: 60 | apiVersion: 61 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 62 | type: string 63 | kind: 64 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 65 | type: string 66 | spec: 67 | description: spec defines properties of a VolumeSnapshotContent created by the underlying storage system. Required. 68 | properties: 69 | deletionPolicy: 70 | description: deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. For dynamically provisioned snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeSnapshotContent object. Required. 71 | enum: 72 | - Delete 73 | - Retain 74 | type: string 75 | driver: 76 | description: driver is the name of the CSI driver used to create the physical snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. 77 | type: string 78 | source: 79 | description: source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. 80 | properties: 81 | snapshotHandle: 82 | description: snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. 83 | type: string 84 | volumeHandle: 85 | description: volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot should be dynamically taken from. This field is immutable. 86 | type: string 87 | type: object 88 | oneOf: 89 | - required: ["snapshotHandle"] 90 | - required: ["volumeHandle"] 91 | volumeSnapshotClassName: 92 | description: name of the VolumeSnapshotClass from which this snapshot was (or will be) created. Note that after provisioning, the VolumeSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. 93 | type: string 94 | volumeSnapshotRef: 95 | description: volumeSnapshotRef specifies the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to this VolumeSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent object, name and namespace of the VolumeSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. 96 | properties: 97 | apiVersion: 98 | description: API version of the referent. 99 | type: string 100 | fieldPath: 101 | description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.' 102 | type: string 103 | kind: 104 | description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 105 | type: string 106 | name: 107 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' 108 | type: string 109 | namespace: 110 | description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' 111 | type: string 112 | resourceVersion: 113 | description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' 114 | type: string 115 | uid: 116 | description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' 117 | type: string 118 | type: object 119 | required: 120 | - deletionPolicy 121 | - driver 122 | - source 123 | - volumeSnapshotRef 124 | type: object 125 | status: 126 | description: status represents the current information of a snapshot. 127 | properties: 128 | creationTime: 129 | description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it indicates the creation time is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command `date +%s%N` returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. 130 | format: int64 131 | type: integer 132 | error: 133 | description: error is the last observed error during snapshot creation, if any. Upon success after retry, this error field will be cleared. 134 | properties: 135 | message: 136 | description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' 137 | type: string 138 | time: 139 | description: time is the timestamp when the error was encountered. 140 | format: date-time 141 | type: string 142 | type: object 143 | readyToUse: 144 | description: readyToUse indicates if a snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. 145 | type: boolean 146 | restoreSize: 147 | description: restoreSize represents the complete size of the snapshot in bytes. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. 148 | format: int64 149 | minimum: 0 150 | type: integer 151 | snapshotHandle: 152 | description: snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. If not specified, it indicates that dynamic snapshot creation has either failed or it is still in progress. 153 | type: string 154 | type: object 155 | required: 156 | - spec 157 | type: object 158 | served: true 159 | storage: true 160 | subresources: 161 | status: {} 162 | - additionalPrinterColumns: 163 | - description: Indicates if the snapshot is ready to be used to restore a volume. 164 | jsonPath: .status.readyToUse 165 | name: ReadyToUse 166 | type: boolean 167 | - description: Represents the complete size of the snapshot in bytes 168 | jsonPath: .status.restoreSize 169 | name: RestoreSize 170 | type: integer 171 | - description: Determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. 172 | jsonPath: .spec.deletionPolicy 173 | name: DeletionPolicy 174 | type: string 175 | - description: Name of the CSI driver used to create the physical snapshot on the underlying storage system. 176 | jsonPath: .spec.driver 177 | name: Driver 178 | type: string 179 | - description: Name of the VolumeSnapshotClass to which this snapshot belongs. 180 | jsonPath: .spec.volumeSnapshotClassName 181 | name: VolumeSnapshotClass 182 | type: string 183 | - description: Name of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. 184 | jsonPath: .spec.volumeSnapshotRef.name 185 | name: VolumeSnapshot 186 | type: string 187 | - description: Namespace of the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. 188 | jsonPath: .spec.volumeSnapshotRef.namespace 189 | name: VolumeSnapshotNamespace 190 | type: string 191 | - jsonPath: .metadata.creationTimestamp 192 | name: Age 193 | type: date 194 | name: v1beta1 195 | # This indicates the v1beta1 version of the custom resource is deprecated. 196 | # API requests to this version receive a warning in the server response. 197 | deprecated: true 198 | # This overrides the default warning returned to clients making v1beta1 API requests. 199 | deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshotContent is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshotContent" 200 | schema: 201 | openAPIV3Schema: 202 | description: VolumeSnapshotContent represents the actual "on-disk" snapshot object in the underlying storage system 203 | properties: 204 | apiVersion: 205 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 206 | type: string 207 | kind: 208 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 209 | type: string 210 | spec: 211 | description: spec defines properties of a VolumeSnapshotContent created by the underlying storage system. Required. 212 | properties: 213 | deletionPolicy: 214 | description: deletionPolicy determines whether this VolumeSnapshotContent and its physical snapshot on the underlying storage system should be deleted when its bound VolumeSnapshot is deleted. Supported values are "Retain" and "Delete". "Retain" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are kept. "Delete" means that the VolumeSnapshotContent and its physical snapshot on underlying storage system are deleted. For dynamically provisioned snapshots, this field will automatically be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field defined in the corresponding VolumeSnapshotClass. For pre-existing snapshots, users MUST specify this field when creating the VolumeSnapshotContent object. Required. 215 | enum: 216 | - Delete 217 | - Retain 218 | type: string 219 | driver: 220 | description: driver is the name of the CSI driver used to create the physical snapshot on the underlying storage system. This MUST be the same as the name returned by the CSI GetPluginName() call for that driver. Required. 221 | type: string 222 | source: 223 | description: source specifies whether the snapshot is (or should be) dynamically provisioned or already exists, and just requires a Kubernetes object representation. This field is immutable after creation. Required. 224 | properties: 225 | snapshotHandle: 226 | description: snapshotHandle specifies the CSI "snapshot_id" of a pre-existing snapshot on the underlying storage system for which a Kubernetes object representation was (or should be) created. This field is immutable. 227 | type: string 228 | volumeHandle: 229 | description: volumeHandle specifies the CSI "volume_id" of the volume from which a snapshot should be dynamically taken from. This field is immutable. 230 | type: string 231 | type: object 232 | volumeSnapshotClassName: 233 | description: name of the VolumeSnapshotClass from which this snapshot was (or will be) created. Note that after provisioning, the VolumeSnapshotClass may be deleted or recreated with different set of values, and as such, should not be referenced post-snapshot creation. 234 | type: string 235 | volumeSnapshotRef: 236 | description: volumeSnapshotRef specifies the VolumeSnapshot object to which this VolumeSnapshotContent object is bound. VolumeSnapshot.Spec.VolumeSnapshotContentName field must reference to this VolumeSnapshotContent's name for the bidirectional binding to be valid. For a pre-existing VolumeSnapshotContent object, name and namespace of the VolumeSnapshot object MUST be provided for binding to happen. This field is immutable after creation. Required. 237 | properties: 238 | apiVersion: 239 | description: API version of the referent. 240 | type: string 241 | fieldPath: 242 | description: 'If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. For example, if the object reference is to a container within a pod, this would take on a value like: "spec.containers{name}" (where "name" refers to the name of the container that triggered the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. TODO: this design is not final and this field is subject to change in the future.' 243 | type: string 244 | kind: 245 | description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 246 | type: string 247 | name: 248 | description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' 249 | type: string 250 | namespace: 251 | description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' 252 | type: string 253 | resourceVersion: 254 | description: 'Specific resourceVersion to which this reference is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' 255 | type: string 256 | uid: 257 | description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' 258 | type: string 259 | type: object 260 | required: 261 | - deletionPolicy 262 | - driver 263 | - source 264 | - volumeSnapshotRef 265 | type: object 266 | status: 267 | description: status represents the current information of a snapshot. 268 | properties: 269 | creationTime: 270 | description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it indicates the creation time is unknown. The format of this field is a Unix nanoseconds time encoded as an int64. On Unix, the command `date +%s%N` returns the current time in nanoseconds since 1970-01-01 00:00:00 UTC. 271 | format: int64 272 | type: integer 273 | error: 274 | description: error is the last observed error during snapshot creation, if any. Upon success after retry, this error field will be cleared. 275 | properties: 276 | message: 277 | description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' 278 | type: string 279 | time: 280 | description: time is the timestamp when the error was encountered. 281 | format: date-time 282 | type: string 283 | type: object 284 | readyToUse: 285 | description: readyToUse indicates if a snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. 286 | type: boolean 287 | restoreSize: 288 | description: restoreSize represents the complete size of the snapshot in bytes. In dynamic snapshot creation case, this field will be filled in by the CSI snapshotter sidecar with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. 289 | format: int64 290 | minimum: 0 291 | type: integer 292 | snapshotHandle: 293 | description: snapshotHandle is the CSI "snapshot_id" of a snapshot on the underlying storage system. If not specified, it indicates that dynamic snapshot creation has either failed or it is still in progress. 294 | type: string 295 | type: object 296 | required: 297 | - spec 298 | type: object 299 | served: true 300 | storage: false 301 | subresources: 302 | status: {} 303 | status: 304 | acceptedNames: 305 | kind: "" 306 | plural: "" 307 | conditions: [] 308 | storedVersions: [] 309 | -------------------------------------------------------------------------------- /VolumeSnapshot/snapshot.storage.k8s.io_volumesnapshots.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.4.0 8 | api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/419" 9 | creationTimestamp: null 10 | name: volumesnapshots.snapshot.storage.k8s.io 11 | spec: 12 | group: snapshot.storage.k8s.io 13 | names: 14 | kind: VolumeSnapshot 15 | listKind: VolumeSnapshotList 16 | plural: volumesnapshots 17 | shortNames: 18 | - vs 19 | singular: volumesnapshot 20 | scope: Namespaced 21 | versions: 22 | - additionalPrinterColumns: 23 | - description: Indicates if the snapshot is ready to be used to restore a volume. 24 | jsonPath: .status.readyToUse 25 | name: ReadyToUse 26 | type: boolean 27 | - description: If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created. 28 | jsonPath: .spec.source.persistentVolumeClaimName 29 | name: SourcePVC 30 | type: string 31 | - description: If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot. 32 | jsonPath: .spec.source.volumeSnapshotContentName 33 | name: SourceSnapshotContent 34 | type: string 35 | - description: Represents the minimum size of volume required to rehydrate from this snapshot. 36 | jsonPath: .status.restoreSize 37 | name: RestoreSize 38 | type: string 39 | - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. 40 | jsonPath: .spec.volumeSnapshotClassName 41 | name: SnapshotClass 42 | type: string 43 | - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. 44 | jsonPath: .status.boundVolumeSnapshotContentName 45 | name: SnapshotContent 46 | type: string 47 | - description: Timestamp when the point-in-time snapshot was taken by the underlying storage system. 48 | jsonPath: .status.creationTime 49 | name: CreationTime 50 | type: date 51 | - jsonPath: .metadata.creationTimestamp 52 | name: Age 53 | type: date 54 | name: v1 55 | schema: 56 | openAPIV3Schema: 57 | description: VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. 58 | properties: 59 | apiVersion: 60 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 61 | type: string 62 | kind: 63 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 64 | type: string 65 | spec: 66 | description: 'spec defines the desired characteristics of a snapshot requested by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots Required.' 67 | properties: 68 | source: 69 | description: source specifies where a snapshot will be created from. This field is immutable after creation. Required. 70 | properties: 71 | persistentVolumeClaimName: 72 | description: persistentVolumeClaimName specifies the name of the PersistentVolumeClaim object representing the volume from which a snapshot should be created. This PVC is assumed to be in the same namespace as the VolumeSnapshot object. This field should be set if the snapshot does not exists, and needs to be created. This field is immutable. 73 | type: string 74 | volumeSnapshotContentName: 75 | description: volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent object representing an existing volume snapshot. This field should be set if the snapshot already exists and only needs a representation in Kubernetes. This field is immutable. 76 | type: string 77 | type: object 78 | oneOf: 79 | - required: ["persistentVolumeClaimName"] 80 | - required: ["volumeSnapshotContentName"] 81 | volumeSnapshotClassName: 82 | description: 'VolumeSnapshotClassName is the name of the VolumeSnapshotClass requested by the VolumeSnapshot. VolumeSnapshotClassName may be left nil to indicate that the default SnapshotClass should be used. A given cluster may have multiple default Volume SnapshotClasses: one default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, VolumeSnapshotSource will be checked to figure out what the associated CSI Driver is, and the default VolumeSnapshotClass associated with that CSI Driver will be used. If more than one VolumeSnapshotClass exist for a given CSI Driver and more than one have been marked as default, CreateSnapshot will fail and generate an event. Empty string is not allowed for this field.' 83 | type: string 84 | required: 85 | - source 86 | type: object 87 | status: 88 | description: status represents the current information of a snapshot. Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. 89 | properties: 90 | boundVolumeSnapshotContentName: 91 | description: 'boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent object to which this VolumeSnapshot object intends to bind to. If not specified, it indicates that the VolumeSnapshot object has not been successfully bound to a VolumeSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object.' 92 | type: string 93 | creationTime: 94 | description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it may indicate that the creation time of the snapshot is unknown. 95 | format: date-time 96 | type: string 97 | error: 98 | description: error is the last observed error during snapshot creation, if any. This field could be helpful to upper level controllers(i.e., application controller) to decide whether they should continue on waiting for the snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurrs during the snapshot creation. Upon success, this error field will be cleared. 99 | properties: 100 | message: 101 | description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' 102 | type: string 103 | time: 104 | description: time is the timestamp when the error was encountered. 105 | format: date-time 106 | type: string 107 | type: object 108 | readyToUse: 109 | description: readyToUse indicates if the snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. 110 | type: boolean 111 | restoreSize: 112 | type: string 113 | description: restoreSize represents the minimum size of volume required to create a volume from this snapshot. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. 114 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 115 | x-kubernetes-int-or-string: true 116 | type: object 117 | required: 118 | - spec 119 | type: object 120 | served: true 121 | storage: true 122 | subresources: 123 | status: {} 124 | - additionalPrinterColumns: 125 | - description: Indicates if the snapshot is ready to be used to restore a volume. 126 | jsonPath: .status.readyToUse 127 | name: ReadyToUse 128 | type: boolean 129 | - description: If a new snapshot needs to be created, this contains the name of the source PVC from which this snapshot was (or will be) created. 130 | jsonPath: .spec.source.persistentVolumeClaimName 131 | name: SourcePVC 132 | type: string 133 | - description: If a snapshot already exists, this contains the name of the existing VolumeSnapshotContent object representing the existing snapshot. 134 | jsonPath: .spec.source.volumeSnapshotContentName 135 | name: SourceSnapshotContent 136 | type: string 137 | - description: Represents the minimum size of volume required to rehydrate from this snapshot. 138 | jsonPath: .status.restoreSize 139 | name: RestoreSize 140 | type: string 141 | - description: The name of the VolumeSnapshotClass requested by the VolumeSnapshot. 142 | jsonPath: .spec.volumeSnapshotClassName 143 | name: SnapshotClass 144 | type: string 145 | - description: Name of the VolumeSnapshotContent object to which the VolumeSnapshot object intends to bind to. Please note that verification of binding actually requires checking both VolumeSnapshot and VolumeSnapshotContent to ensure both are pointing at each other. Binding MUST be verified prior to usage of this object. 146 | jsonPath: .status.boundVolumeSnapshotContentName 147 | name: SnapshotContent 148 | type: string 149 | - description: Timestamp when the point-in-time snapshot was taken by the underlying storage system. 150 | jsonPath: .status.creationTime 151 | name: CreationTime 152 | type: date 153 | - jsonPath: .metadata.creationTimestamp 154 | name: Age 155 | type: date 156 | name: v1beta1 157 | # This indicates the v1beta1 version of the custom resource is deprecated. 158 | # API requests to this version receive a warning in the server response. 159 | deprecated: true 160 | # This overrides the default warning returned to clients making v1beta1 API requests. 161 | deprecationWarning: "snapshot.storage.k8s.io/v1beta1 VolumeSnapshot is deprecated; use snapshot.storage.k8s.io/v1 VolumeSnapshot" 162 | schema: 163 | openAPIV3Schema: 164 | description: VolumeSnapshot is a user's request for either creating a point-in-time snapshot of a persistent volume, or binding to a pre-existing snapshot. 165 | properties: 166 | apiVersion: 167 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 168 | type: string 169 | kind: 170 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 171 | type: string 172 | spec: 173 | description: 'spec defines the desired characteristics of a snapshot requested by a user. More info: https://kubernetes.io/docs/concepts/storage/volume-snapshots#volumesnapshots Required.' 174 | properties: 175 | source: 176 | description: source specifies where a snapshot will be created from. This field is immutable after creation. Required. 177 | properties: 178 | persistentVolumeClaimName: 179 | description: persistentVolumeClaimName specifies the name of the PersistentVolumeClaim object representing the volume from which a snapshot should be created. This PVC is assumed to be in the same namespace as the VolumeSnapshot object. This field should be set if the snapshot does not exists, and needs to be created. This field is immutable. 180 | type: string 181 | volumeSnapshotContentName: 182 | description: volumeSnapshotContentName specifies the name of a pre-existing VolumeSnapshotContent object representing an existing volume snapshot. This field should be set if the snapshot already exists and only needs a representation in Kubernetes. This field is immutable. 183 | type: string 184 | type: object 185 | volumeSnapshotClassName: 186 | description: 'VolumeSnapshotClassName is the name of the VolumeSnapshotClass requested by the VolumeSnapshot. VolumeSnapshotClassName may be left nil to indicate that the default SnapshotClass should be used. A given cluster may have multiple default Volume SnapshotClasses: one default per CSI Driver. If a VolumeSnapshot does not specify a SnapshotClass, VolumeSnapshotSource will be checked to figure out what the associated CSI Driver is, and the default VolumeSnapshotClass associated with that CSI Driver will be used. If more than one VolumeSnapshotClass exist for a given CSI Driver and more than one have been marked as default, CreateSnapshot will fail and generate an event. Empty string is not allowed for this field.' 187 | type: string 188 | required: 189 | - source 190 | type: object 191 | status: 192 | description: status represents the current information of a snapshot. Consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object. 193 | properties: 194 | boundVolumeSnapshotContentName: 195 | description: 'boundVolumeSnapshotContentName is the name of the VolumeSnapshotContent object to which this VolumeSnapshot object intends to bind to. If not specified, it indicates that the VolumeSnapshot object has not been successfully bound to a VolumeSnapshotContent object yet. NOTE: To avoid possible security issues, consumers must verify binding between VolumeSnapshot and VolumeSnapshotContent objects is successful (by validating that both VolumeSnapshot and VolumeSnapshotContent point at each other) before using this object.' 196 | type: string 197 | creationTime: 198 | description: creationTime is the timestamp when the point-in-time snapshot is taken by the underlying storage system. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "creation_time" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "creation_time" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. If not specified, it may indicate that the creation time of the snapshot is unknown. 199 | format: date-time 200 | type: string 201 | error: 202 | description: error is the last observed error during snapshot creation, if any. This field could be helpful to upper level controllers(i.e., application controller) to decide whether they should continue on waiting for the snapshot to be created based on the type of error reported. The snapshot controller will keep retrying when an error occurrs during the snapshot creation. Upon success, this error field will be cleared. 203 | properties: 204 | message: 205 | description: 'message is a string detailing the encountered error during snapshot creation if specified. NOTE: message may be logged, and it should not contain sensitive information.' 206 | type: string 207 | time: 208 | description: time is the timestamp when the error was encountered. 209 | format: date-time 210 | type: string 211 | type: object 212 | readyToUse: 213 | description: readyToUse indicates if the snapshot is ready to be used to restore a volume. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "ready_to_use" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "ready_to_use" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it, otherwise, this field will be set to "True". If not specified, it means the readiness of a snapshot is unknown. 214 | type: boolean 215 | restoreSize: 216 | type: string 217 | description: restoreSize represents the minimum size of volume required to create a volume from this snapshot. In dynamic snapshot creation case, this field will be filled in by the snapshot controller with the "size_bytes" value returned from CSI "CreateSnapshot" gRPC call. For a pre-existing snapshot, this field will be filled with the "size_bytes" value returned from the CSI "ListSnapshots" gRPC call if the driver supports it. When restoring a volume from this snapshot, the size of the volume MUST NOT be smaller than the restoreSize if it is specified, otherwise the restoration will fail. If not specified, it indicates that the size is unknown. 218 | pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ 219 | x-kubernetes-int-or-string: true 220 | type: object 221 | required: 222 | - spec 223 | type: object 224 | served: true 225 | storage: false 226 | subresources: 227 | status: {} 228 | status: 229 | acceptedNames: 230 | kind: "" 231 | plural: "" 232 | conditions: [] 233 | storedVersions: [] 234 | -------------------------------------------------------------------------------- /bin/linux-amd64/tridentctl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qnap-dev/QNAP-CSI-PlugIn/998e68d77187c7d881a8f0aee8c3d69a28626902/bin/linux-amd64/tridentctl -------------------------------------------------------------------------------- /bin/linux-arm64/tridentctl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qnap-dev/QNAP-CSI-PlugIn/998e68d77187c7d881a8f0aee8c3d69a28626902/bin/linux-arm64/tridentctl -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # QNAP CSI Driver for Kubernetes 2 | This is the official [Container Storage Interface](https://github.com/container-storage-interface) (CSI) driver for QNAP NAS devices. 3 | 4 | ## Table of Contents 5 | * [Introduction](#Introduction) 6 | * [Software Prerequisites](#Software-Prerequisites) 7 | * [Supported Features](#Supported-Features) 8 | * [Installation](#Installation) 9 | * [CSI Driver Configuration](#CSI-Driver-Configuration) 10 | * [Deployment](#Deployment) 11 | * [Operations](#Operations) 12 | 13 | 14 | ## Introduction 15 | The QNAP CSI driver is a storage service designed to provide volumes from local or remote NAS devices to Kubernetes. It is based on [NetApp Trident](http://github.com/NetApp/Trident), providing dynamic volume provisioning. The driver supports quality of service (QoS) assignment to ensure optimal performance tailored to application needs. 16 | 17 | The key concepts in this driver are `backend` and `pools`. A backend represents the NAS storage used for [PersistentVolumeClaim (PVC)](https://reurl.cc/DlYzZe) requests. Each backend contains virtual pools, which are logical groupings of storage that dynamically select an appropriate physical pool based on specific requirements. PVCs request storage through a [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/), which binds to the virtual pool, ensuring the volume is created from the correct physical resources. The process for creating a volume using this driver is as follows (also illustrated in Figure 1): 18 | 19 | 1. The user claims a PVC request specifying a StorageClass. 20 | 2. The system binds the request to a suitable virtual pool configured in the backend. 21 | 3. The system filters the available physical pools based on the required features. 22 | 4. A suitable physical pool is selected from the filtered options. 23 | 5. The requested volume is created on the selected physical pool. 24 | > [!Tip] 25 | > The system prioritizes selecting the backend with the lowest current volume usage to ensure load balancing. 26 | 27 | [![create.png](https://i.postimg.cc/cC6YjCNq/create.png)](https://postimg.cc/YLKhLp98) 28 | Figure 1. Process of creating a volume with the QNAP CSI driver. 29 | 30 | 31 | ## Software Prerequisites 32 | ### CSI Driver Version and Compatibility 33 | | **Driver Version** | **Supported Kubernetes Versions** | **Supported QNAP NAS Operating Systems** | 34 | |------------------- | --------------------------------- | ------------------------------------- | 35 | | v1.5.0 | v1.24 to v1.32 | QTS 5.0.0 or later
QuTS hero h5.0.0 or later| 36 | 37 | ### Supported Host Operating Systems 38 | - Debian 8 or later 39 | - Ubuntu 16.04 or later 40 | - CentOS 7.0 or later 41 | - RHEL 7.0 or later 42 | - CoreOS 1353.8.0 or later 43 | - Talos 1.8 or later 44 | 45 | ### Supported Platforms 46 | - AMD64 47 | - ARM64 and ARMv7 48 | 49 | 50 | ## Supported Features 51 | 52 | * Protocol: iSCSI, Samba 53 | * Access mode: ReadWriteOnce, ReadWriteMany 54 | * Cloning 55 | * Snapshots 56 | * Expansion 57 | * Pool level: RAID levels, SSD cache, Tiering 58 | * Volume level: Threshold, ThinAllocate, Compression, Deduplication 59 | 60 | 61 | ## Installation 62 | ### Preinstallation Checklist 63 | 64 | * Ensure that both the Kubernetes and the QNAP NAS operating system versions are supported. 65 | > [!NOTE] 66 | > Minikube is not supported. 67 | * If the iSCSI protocol is utilized. Install open-iscsi in Kubernetes by running the following command in both the master and worker nodes: 68 | ``` 69 | sudo apt install open-iscsi 70 | ``` 71 | * Verify that your NAS has at least one available storage pool and iSCSI service is enabled. 72 | - To check storage pools on your NAS, open Storage & Snapshots and navigate to "Storage > Storage/Snapshots". 73 | - If the iSCSI protocol is utilized. To check iSCSI service on your NAS, open iSCSI & Fibre Channel and verify that the "Service" toggle switch is on. 74 |
Verify your Kubernetes cluster. 75 | 76 | ### Verifying Your Kubernetes Cluster 77 | * Make sure `kubectl` is installed and working. 78 | ``` 79 | kubectl get pods -A 80 | ``` 81 | ``` 82 | kubectl version 83 | ``` 84 | Verify that both commands return expected results without errors. 85 | 86 | * Make sure that you are logged in as a Kubernetes cluster administrator. 87 | ``` 88 | kubectl auth can-i '*' '*' --all-namespaces 89 | ``` 90 | The command should return `yes`. 91 | 92 | * Verify that you can launch a pod using an image from Docker Hub and check connectivity to the storage system over the pod network. 93 | ``` 94 | kubectl run -i --tty ping --image=busybox --restart=Never --rm -- \ping 95 | ``` 96 | For example: `kubectl run -i --tty ping --image=busybox --restart=Never --rm -- \ping 8.8.8.8` 97 | A successful test will display packet responses, indicating connectivity. The pod will automatically delete itself after completion. 98 |
99 | 100 | ### Install the QNAP CSI Plugin 101 | 1. Clone the git repository. 102 | ``` 103 | sudo git clone https://github.com/qnap-dev/QNAP-CSI-PlugIn.git 104 | ``` 105 | 2. Navigate to the directory. 106 | ``` 107 | cd QNAP-CSI-PlugIn 108 | ``` 109 | 3. Choose one of the following installation methods. 110 | 111 | * Installing via kubectl 112 | 113 | Execute the following commands in order: 114 | ``` 115 | kubectl apply -f Deploy/Trident/namespace.yaml 116 | ``` 117 | ``` 118 | kubectl apply -f Deploy/crds/tridentorchestrator_crd.yaml 119 | ``` 120 | ``` 121 | kubectl apply -f Deploy/Trident/bundle.yaml 122 | ``` 123 | ``` 124 | kubectl apply -f Deploy/Trident/tridentorchestrator.yaml 125 | ``` 126 | 127 | * Installing via Kustomize 128 | 129 | Execute the following commands in order: 130 | ``` 131 | kubectl apply -k Deploy/crds 132 | ``` 133 | ``` 134 | kubectl apply -k Deploy/Trident 135 | ``` 136 | 137 | * Installing via Helm 138 | 1. Install Helm. 139 | 140 | Please refer to the [Helm Installation Guide](https://helm.sh/docs/intro/install/) for instructions. 141 | 142 | 2. Install the CSI plugin. 143 | ``` 144 | helm install qnap-trident ./Helm/trident -n trident --create-namespace 145 | ``` 146 | 147 | 3. Upgrade the plugin. 148 | ``` 149 | helm upgrade qnap-trident Helm/trident/ -n trident 150 | ``` 151 | 152 | ### Install VolumeSnapshot (Optional) 153 | A VolumeSnapshot is required to take snapshots. 154 | ``` 155 | kubectl apply -k VolumeSnapshot 156 | ``` 157 | 158 | ### Check that Trident is Ready 159 | 1. Check the status of Trident. 160 | 161 | ``` 162 | kubectl get deployment -n trident 163 | ``` 164 | The output should display both `trident-controller` and `trident-operator` as being ready.
Example output: 165 | [![trident-ready.png](https://i.postimg.cc/zGx1qkC6/trident-ready.png)](https://postimg.cc/75JRV0Qn) 166 | 2. Verify the Trident service. 167 | 168 | ``` 169 | kubectl get service -n trident 170 | ``` 171 | The output should include `trident-csi`.
Example output: 172 | [![trident-ready2.png](https://i.postimg.cc/PrhGZ7K0/trident-ready2.png)](https://postimg.cc/7bBQrmFN) 173 | 174 | 175 | ## CSI Driver Configuration 176 | To ensure the CSI driver functions correctly, it is important to configure the backend, secert (Optional), StorageClass, and PVC with matching labels and parameters to enable proper binding. The backend defines the virtual storage pools and connects the underlying physical resources, the secret is required when the Samba protocol is utilized for connection, while the StorageClass specifies the QoS that the PVC will request. 177 | 178 | For binding to succeed, the PVC must reference a StorageClass that has the correct labels and selectors, which correspond to the virtual pools defined in the backend. Accurate configuration of names, labels, and selectors in each component is essential to ensure the PVC is correctly bound to the appropriate storage resources through the backend and StorageClass. 179 | 180 | ### Backend 181 | There are two methods for configuring the backend: 182 | * Custom resource (`TridentBackendConfig`) 183 | * CLI (`tridentctl`). 184 | 185 | > [!TIP] 186 | > We recommend using the newer custom resource method over the legacy CLI method. 187 | 188 | 1. Create or edit a YAML file (for the custom resource method) or a JSON file (for the CLI method).
189 | Please refer to the following examples. 190 | 191 | * Custom resource method
192 | Example: `Samples/Backend/backend-sample.yaml` 193 | 194 | ```yaml 195 | apiVersion: v1 196 | kind: Secret 197 | metadata: 198 | name: backend-qts-secret # Required. Name your secret. 199 | namespace: trident 200 | type: Opaque 201 | stringData: 202 | username: user # Required. Your NAS username. 203 | password: 0000 # Required. Your NAS password. 204 | storageAddress: 0.0.0.0 # Required. Your NAS IP address. 205 | --- 206 | apiVersion: trident.qnap.io/v1 207 | kind: TridentBackendConfig 208 | metadata: 209 | name: backend-qts # Required. Name your backend in Kubernetes. 210 | namespace: trident 211 | spec: 212 | version: 1 213 | storageDriverName: qnap-nas #Required. Support 'qnap-nas'(latest) or 'qnap-iscsi' 214 | backendName: qts # Required. Name your backend in QNAP CSI. 215 | networkInterfaces: ["Adapter1"] # Optional. Your adapter name or leave it empty. 216 | credentials: 217 | name: backend-qts-secret # Required. Enter the secret name set in metadata.name. 218 | debugTraceFlags: 219 | method: true 220 | storage: # Required. Define one or more virtual pools. 221 | - serviceLevel: pool1 # Required. Name your virtual pool. 222 | labels: # Required. Define custom labels for your virtual pool. 223 | performance: performance1 224 | features: # Optional. Define features for your virtual pool. 225 | tiering: Enable 226 | - serviceLevel: pool2 227 | labels: 228 | performance: performance2 229 | features: 230 | tiering: Enable 231 | ssdCache: "true" 232 | raidLevel: "1" 233 | ``` 234 | 235 | * CLI method
236 | Example: `Samples/Backend/backend-sample.json`. 237 | ```json 238 | { 239 | "version": 1, 240 | "storageDriverName": "qnap-nas", 241 | "backendName": "qts", 242 | "storageAddress": "0.0.0.0", 243 | "username": "user", 244 | "password": "0000", 245 | "networkInterfaces": ["Adapter1"], 246 | "debugTraceFlags": {"method": true}, 247 | "storage": [ 248 | { 249 | "labels": {"performance": "performance1"}, 250 | "features":{ 251 | "tiering": "Enable" 252 | }, 253 | "serviceLevel": "pool1" 254 | }, 255 | { 256 | "labels": {"performance": "performance2"}, 257 | "features":{ 258 | "tiering": "Enable", 259 | "ssdCache": "true", 260 | "raidLevel": "1" 261 | }, 262 | "serviceLevel": "pool2" 263 | }, 264 | ] 265 | } 266 | ``` 267 | 268 | 2. In the YAML or JSON file, configure the following based on your NAS settings and usage requirements. 269 | * Specify the correct NAS `user`, `password`, and `IP address`. 270 | * Name the secret and backend. 271 | * Optional: Set the network portal in the `networkInterfaces` field. 272 | 273 | > **Note:**
274 | > Network settings support physical and virtual adapters. In the `networkInterfaces` field, assign an interface name (e.g., \["Adapter1"\]) or leave it empty to default to `storageAddress`. To view the available adapters on your NAS, open Network & Virtual Switch and go to "Interfaces". 275 | 276 | * Define the virtual pools based on your usage requirements. 277 | | Field | Description | Example | 278 | |------------------------------|------------------------|---------| 279 | | serviceLevel | Name the virtual pool. | serviceLevel: pool1 | 280 | | labels | Label the virtual pool with any key/value. | usage: test | 281 | | features | Define the virtual pool with the specified features from the feature list below. | features:
  ssdCache: "true" 282 | 283 | Feature list: 284 | | Feature | Description |Value | Note | 285 | |-----------|----------|--------|----------| 286 | | raidLevel | Combines multiple disks to improve both redundancy and performance. |0, 1, 5, 6, etc. | | 287 | | ssdCache | Boosts NAS performance by caching frequently accessed data on SSDs, reducing latency and speeding up access. |true, false | | 288 | | tiering | Moves hot data to high-performance drives and cold data to cost-efficient drives, optimizing performance and total cost of operation.|enable, disable | Only QTS | 289 | 290 | ### Secert 291 | If the Samba protocol is utilized, the `Secert` configuration is required. 292 | Create or edit the YAML file `Samples/Secret/smb_user_secret.yaml`\ 293 | Example: 294 | ```yaml 295 | apiVersion: v1 296 | kind: Secret 297 | metadata: 298 | name: qts-csi-smb #Required. Name your secert for Samba. 299 | namespace: trident 300 | type: Opaque 301 | stringData: 302 | username: user1 #Required. The valid Samba username on the NAS. 303 | password: 0000 #Required. The valid Samba password on the NAS. 304 | ``` 305 | 306 | ### StorageClass 307 | 1. Create or edit the YAML file.
308 | 309 | iSCSI: `Samples/StorageClass/sc_iscsi_sample.yaml`.
310 | 311 | Example: 312 | ```yaml 313 | apiVersion: storage.k8s.io/v1 314 | kind: StorageClass 315 | metadata: 316 | name: storageclass1 # Required. Name your storageclass. 317 | provisioner: csi.trident.qnap.io 318 | parameters: 319 | selector: "performance=performance1" # Required. Corresponds to the labels in the virtual pool. 320 | fsType: "ext4" # Optional. You can choose to enter ext4 (default), xfs, or ext3. 321 | allowVolumeExpansion: true 322 | ``` 323 | Samba: `Samples/StorageClass/sc_smb_sample.yaml`.
324 | 325 | Example: 326 | 327 | ```yaml 328 | apiVersion: storage.k8s.io/v1 329 | kind: StorageClass 330 | metadata: 331 | name: storageclass1 # Required. Name your storageclass. 332 | provisioner: csi.trident.qnap.io 333 | parameters: 334 | selector: "performance=performance1" # Required. Corresponds to the labels in the virtual pool. 335 | trident.qnap.io/fileProtocol: "smb" 336 | csi.storage.k8s.io/node-stage-secret-name: "qts-csi-smb" # Required. It must match the metadata.name in the Secret file. 337 | csi.storage.k8s.io/node-stage-secret-namespace: "trident" # Required. It must match the metadata.namespace in the Secret file. 338 | allowVolumeExpansion: true 339 | ``` 340 | 2. Configure the file based on your usage requirements. 341 | 342 | Bind the backend's virtual pool using the parameters.selector field, ensuring it matches the labels in the virtual pool. 343 | 344 | ### PVC 345 | 1. Create or edit the YAML file `Samples/Volumes/pvc-sample.yaml`
346 | Example: 347 | ```yaml 348 | kind: PersistentVolumeClaim 349 | apiVersion: v1 350 | metadata: 351 | name: pvc1 352 | annotations: # Required. Define features for your volume. 353 | trident.qnap.io/Threshold: "90" 354 | trident.qnap.io/ThinAllocate: "true" 355 | spec: 356 | accessModes: 357 | - ReadWriteOnce # Required. iSCSI: ReadWriteOnce, Samba: ReadWriteMany 358 | resources: 359 | requests: 360 | storage: 10Gi # Required. Specify your resource size. 361 | storageClassName: storageclass1 # Required. Corresponds to the StorageClass name. 362 | ``` 363 | 364 | 2. Configure the file based on your usage requirements. 365 | 366 | * Bind the StorageClass using the `storageClassName` field. 367 | * Set your volume feature requirements in the `annotations` field using the prefix `trident.qnap.io/`. For example, `trident.qnap.io/threshold: "90"`. Refer to the following table for details. 368 | 369 | Volume features: 370 | | Feature | Description |Value | Note | 371 | |--------------------|--------|------|----------------| 372 | | Threshold | Monitors storage usage to trigger alerts when capacity limits are reached, preventing overuse. |0-100 | | 373 | | ThinAllocate | Dynamically allocates storage space to meet demands, optimizing usage and avoiding shortages. |true, false | 374 | | SharedFolderRecycleBin | Enable or disable the Recycle Bin based on your needs. |true, false |SMB protocol only | 375 | | Compression | Compresses files to reduce size, saving space and allowing more storage on the NAS. |true, false | Only QuTS hero | 376 | | Deduplication | Eliminates duplicate data to reduce storage needs and minimize network data transfers.|true, false | Only QuTS hero | 377 | | FastClone | Creates file copies faster to save space by sharing data blocks between originals and copies.|true, false | Only QuTS hero | 378 | | importOriginalName | The original volume name. | string | Refer to [Importing a PVC](#importing-a-pvc) in the "Operations" section. | 379 | | importBackendName | The imported backend name. |string | Refer to [Importing a PVC](#importing-a-pvc) in the "Operations" section. | 380 | 381 | 382 | ## Deployment 383 | When building the service, add the backend, the StorageClass, and then the PVC, in this order. 384 | 385 | ### 1. Add a Backend 386 | Make sure you have a corresponding pool, and based on the type of your backend configuration file, choose one of the following methods to add the pool. 387 | 388 | * Using the custom resource method to add a backend with the YAML file 389 | 390 | a. Add a backend based on the YAML file you configured earlier. 391 | ``` 392 | kubectl apply -f 393 | ``` 394 | For example: `kubectl apply -f Samples/Backend/backend-sample.yaml` 395 | 396 | b. Check the result. 397 | ``` 398 | kubectl get tridentbackendconfig -n trident 399 | ``` 400 | 401 | * Using the CLI method to add a backend with the JSON file 402 | 403 | a. Ensure you have permission to execute `tridentctl`. 404 | ``` 405 | chmod u+x tridentctl 406 | ``` 407 | 408 | b. Add a backend based on the JSON file you configured earlier. 409 | ``` 410 | ./ create backend -f -n trident 411 | ``` 412 | For example: `./bin/linux-amd64/tridentctl create backend -f Samples/Backend/backend-sample.json -n trident` 413 | 414 | > [!NOTE] 415 | > If it takes over 30 seconds and shows the error "Command terminated with exit code 1" due to timeout, check your network connection and try again. 416 | 417 | After adding the backend, check the result. 418 | ``` 419 | kubectl get pods -n trident 420 | ``` 421 | 422 | 423 | ### 2. Add a StorageClass 424 | Execute the following command: 425 | ``` 426 | kubectl apply -f 427 | ``` 428 | For example: `kubectl apply -f Samples/StorageClass/sc-sample.yaml` 429 | 430 | > [!NOTE] 431 | > If you want to use the SMB protocol, please execute the following command and apply the corresponding Secret before adding the StorageClass. 432 | >``` 433 | >kubectl apply -f 434 | >``` 435 | > For example: `kubectl apply -f Samples/Secret/smb_user_secret.yaml` 436 | 437 | ### 3. Add a PVC 438 | Execute the following command: 439 | ``` 440 | kubectl apply -f 441 | ``` 442 | For example: `kubectl apply -f Samples/Volumes/pvc-sample.yaml` 443 | 444 | ### 4. Verify the Connection (Optional) 445 | 446 | After completing the deployment steps, verify if the connection is mapped in iSCSI & Fibre Channel on the NAS. You should locate the connection in the "iSCSI Target List" on the "iSCSI Storage" page, as shown in the red frame in Figure 2. 447 | 448 | [![nas-iscsi.png](https://i.postimg.cc/qM02cB84/nas-iscsi.png)](https://postimg.cc/vDq1bsqN) 449 |

Figure 2. Checking the iSCSI target connection.

450 | 451 | 452 | ## Operations 453 | ### Expanding a PVC 454 | ``` 455 | kubectl edit pvc 456 | ``` 457 | For example: `kubectl edit pvc pvc-sample` 458 | 459 | After a few seconds, the capacity will increase on the NAS. 460 | After the pod restarts, the capacity information will be updated. 461 | 462 | ### Cloning a PVC 463 | 464 | Create or edit the YAML file `Samples/Volumes/pvc-clone.yaml` based on your usage requirements. 465 | 466 | Example: 467 | ```yaml 468 | apiVersion: v1 469 | kind: PersistentVolumeClaim 470 | metadata: 471 | name: pvc-from-clone 472 | spec: 473 | accessModes: 474 | - ReadWriteOnce # iSCSI: ReadWriteOnce, Samba: ReadWriteMany 475 | resources: 476 | requests: 477 | storage: 5Gi 478 | dataSource: 479 | kind: PersistentVolumeClaim 480 | name: pvc-sample 481 | storageClassName: storageclass1 482 | ``` 483 | Name the cloned PVC using the `name` field, configure the `storage` field, and assign the source PVC in the `dataSource` field. 484 | >[!Note] 485 | >The cloned PVC's storage size must be greater than or equal to that of the source PVC. 486 | 487 | After configuring the YAML file, run the following command: 488 | ``` 489 | kubectl apply -f 490 | ``` 491 | For example: `kubectl apply -f Samples/Volumes/pvc-clone.yaml` 492 | 493 | 494 | ### Importing a PVC 495 | 496 | iSCSI: 497 | Create or edit the YAML file `Samples/Volumes/pvc-import.yaml` based on your usage requirements. 498 | >[!NOTE] 499 | >Only iSCSI LUNs are supported. 500 | 501 | Example: 502 | ```yaml 503 | kind: PersistentVolumeClaim 504 | apiVersion: v1 505 | metadata: 506 | name: pvc-import-iscsi 507 | namespace: default 508 | annotations: 509 | trident.qnap.io/importOriginalName: "test" 510 | trident.qnap.io/importBackendName: "hero" 511 | spec: 512 | accessModes: 513 | - ReadWriteOnce 514 | resources: 515 | requests: 516 | storage: 10Gi 517 | storageClassName: storageclass1 518 | ``` 519 | After configuring the YAML file, run the following command: 520 | ``` 521 | kubectl apply -f 522 | ``` 523 | For example: `kubectl apply -f Samples/Volumes/pvc-import.yaml` 524 | 525 | Samba: 526 | Create or edit the YAML file `Samples/Volumes/pvc-import.yaml` based on your usage requirements. 527 | ```yaml 528 | kind: PersistentVolumeClaim 529 | apiVersion: v1 530 | metadata: 531 | name: pvc-import-file 532 | annotations: 533 | trident.qnap.io/importOriginalName: "shared-name" 534 | trident.qnap.io/importBackendName: "qts" 535 | spec: 536 | accessModes: 537 | - ReadWriteMany 538 | resources: 539 | requests: 540 | storage: 10Gi #The value entered should correspond to the actual or displayed size. 541 | storageClassName: storageclass1 542 | ``` 543 | >[!Note] 544 | >Due to filesystem limitations in QTS, the capacity shown in "Storage & Snapshot" may be slightly smaller than the specified size when creating a shared folder. For `resources.requests.storage`, enter either the specified size or the displayed size. 545 | For example: 546 | - Specified size: 10GB 547 | - Displayed size: 9.34GB. 548 | [![2025-01-02-120516.png](https://i.postimg.cc/LXcDRJhk/2025-01-02-120516.png)](https://postimg.cc/zbkKFXC3) 549 |
In QuTS Hero, always use the specified size. 550 | 551 | ### Creating a VolumeSnapshot from a PVC 552 | 553 | Create or edit the YAML file `Samples/Snapshot/VolumeSnapshot.yaml` based on your usage requirements. 554 | 555 | Example: 556 | ```yaml 557 | apiVersion: snapshot.storage.k8s.io/v1 558 | kind: VolumeSnapshot 559 | metadata: 560 | name: pvc-snapshot 561 | spec: 562 | volumeSnapshotClassName: trident-snapshotclass 563 | source: 564 | persistentVolumeClaimName: pvc-sample 565 | ``` 566 | After configuring the YAML file, run the following commands one at a time: 567 | ``` 568 | kubectl apply -f 569 | ``` 570 | ``` 571 | kubectl apply -f 572 | ``` 573 | Check the result. 574 | ``` 575 | kubectl get volumesnapshot 576 | ``` 577 | 578 | ### Creating a PVC from a Snapshot 579 | Create or edit the YAML file `Samples/Volumes/pvc-from-snapshot.yaml` based on your usage requirements. 580 | 581 | Example: 582 | ```yaml 583 | kind: PersistentVolumeClaim 584 | apiVersion: v1 585 | metadata: 586 | name: pvc-from-snap 587 | spec: 588 | accessModes: 589 | - ReadWriteOnce # iSCSI: ReadWriteOnce, Samba: ReadWriteMany 590 | resources: 591 | requests: 592 | storage: 5Gi 593 | dataSource: 594 | name: pvc-snapshot 595 | kind: VolumeSnapshot 596 | apiGroup: snapshot.storage.k8s.io 597 | storageClassName: storageclass1 598 | ``` 599 | 600 | After configuring the YAML file, run the following command: 601 | ``` 602 | kubectl apply -f 603 | ``` 604 | 605 | ### Reboot 606 | 607 | Execute the following commands in order: 608 | ``` 609 | kubectl delete tridentorchestrator trident 610 | ``` 611 | ``` 612 | kubectl apply -f Deploy/Trident/tridentorchestrator.yaml 613 | ``` 614 | ### Uninstallation 615 | * Uninstalling via Kustomize (normal method) 616 | Execute the following commands in order: 617 | ``` 618 | kubectl delete deployment trident-operator -n trident 619 | ``` 620 | ``` 621 | ./ uninstall -n trident 622 | ``` 623 | ``` 624 | kubectl delete tridentorchestrator trident 625 | ``` 626 | 627 | * Uninstalling via Helm 628 | ``` 629 | helm delete qnap-trident -n trident 630 | ``` --------------------------------------------------------------------------------