├── unit1 ├── operator │ ├── params.yaml │ ├── templates │ │ ├── config.yaml │ │ └── pod.yaml │ └── operator.yaml └── README.md ├── unit2 ├── operator │ ├── params.yaml │ ├── templates │ │ ├── service.yaml │ │ └── node.yaml │ └── operator.yaml └── README.md ├── unit3 ├── operator │ ├── params.yaml │ ├── templates │ │ ├── service.yaml │ │ └── node.yaml │ └── operator.yaml ├── operator-next │ ├── params.yaml │ ├── templates │ │ ├── service.yaml │ │ └── node.yaml │ └── operator.yaml └── README.md ├── unit4 ├── operator │ ├── params.yaml │ ├── templates │ │ ├── service.yaml │ │ ├── restore.yaml │ │ ├── backup.yaml │ │ └── node.yaml │ └── operator.yaml ├── backup-restore │ ├── backup.yaml │ └── restore.yaml └── README.md ├── README.md └── LICENSE /unit1/operator/params.yaml: -------------------------------------------------------------------------------- 1 | WHO: 2 | default: "Ravi" 3 | -------------------------------------------------------------------------------- /unit2/operator/params.yaml: -------------------------------------------------------------------------------- 1 | NODE_COUNT: 2 | default: "3" 3 | -------------------------------------------------------------------------------- /unit3/operator/params.yaml: -------------------------------------------------------------------------------- 1 | NODE_COUNT: 2 | default: "3" 3 | TEST: 4 | default: "0" 5 | trigger: super 6 | -------------------------------------------------------------------------------- /unit3/operator-next/params.yaml: -------------------------------------------------------------------------------- 1 | NODE_COUNT: 2 | default: "3" 3 | TEST: 4 | default: "0" 5 | trigger: super 6 | -------------------------------------------------------------------------------- /unit1/operator/templates/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: config 5 | namespace: {{ .Namespace }} 6 | data: 7 | index.html: | 8 | {{ .Params.WHO }}, hello from {{ .Name }} !!! 9 | -------------------------------------------------------------------------------- /unit4/operator/params.yaml: -------------------------------------------------------------------------------- 1 | NODE_COUNT: 2 | default: "3" 3 | S3_ACCESS_KEY: 4 | default: "minio" 5 | S3_SECRET_KEY: 6 | default: "minio123" 7 | S3_ENDPOINT: 8 | default: "minio:9000" 9 | RESTORE_SNAPSHOT_ID: 10 | default: "" 11 | -------------------------------------------------------------------------------- /unit2/operator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: hs 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | app: elastic 9 | ports: 10 | - protocol: TCP 11 | port: 9200 12 | clusterIP: None 13 | -------------------------------------------------------------------------------- /unit3/operator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: hs 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | app: elastic 9 | ports: 10 | - protocol: TCP 11 | port: 9200 12 | clusterIP: None 13 | -------------------------------------------------------------------------------- /unit4/operator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: hs 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | app: elastic 9 | ports: 10 | - protocol: TCP 11 | port: 9200 12 | clusterIP: None 13 | -------------------------------------------------------------------------------- /unit3/operator-next/templates/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: hs 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | app: elastic 9 | ports: 10 | - protocol: TCP 11 | port: 9200 12 | clusterIP: None 13 | -------------------------------------------------------------------------------- /unit1/operator/templates/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod 5 | namespace: {{ .Namespace }} 6 | spec: 7 | containers: 8 | - name: nginx 9 | image: nginx 10 | ports: 11 | - containerPort: 80 12 | name: web 13 | volumeMounts: 14 | - name: config 15 | mountPath: /usr/share/nginx/html 16 | volumes: 17 | - name: config 18 | configMap: 19 | name: {{ .Name }}-config 20 | -------------------------------------------------------------------------------- /unit4/backup-restore/backup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kudo.dev/v1alpha1 2 | kind: PlanExecution 3 | metadata: 4 | name: backup 5 | namespace: default 6 | ownerReferences: 7 | - apiVersion: kudo.dev/v1alpha1 8 | blockOwnerDeletion: true 9 | controller: true 10 | kind: Instance 11 | name: myes 12 | uid: e4c10faa-727d-11e9-80a1-0a97366f7696 13 | spec: 14 | instance: 15 | kind: Instance 16 | name: myes 17 | namespace: default 18 | planName: backup 19 | -------------------------------------------------------------------------------- /unit4/backup-restore/restore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kudo.dev/v1alpha1 2 | kind: PlanExecution 3 | metadata: 4 | name: restore 5 | namespace: default 6 | ownerReferences: 7 | - apiVersion: kudo.dev/v1alpha1 8 | blockOwnerDeletion: true 9 | controller: true 10 | kind: Instance 11 | name: myes 12 | uid: e4c10faa-727d-11e9-80a1-0a97366f7696 13 | spec: 14 | instance: 15 | kind: Instance 16 | name: myes 17 | namespace: default 18 | planName: restore 19 | -------------------------------------------------------------------------------- /unit4/operator/templates/restore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: {{ .PlanName }}-job 5 | namespace: default 6 | spec: 7 | template: 8 | metadata: 9 | name: {{ .PlanName }}-job 10 | spec: 11 | restartPolicy: OnFailure 12 | containers: 13 | - name: restore 14 | image: centos:7 15 | command: 16 | - sh 17 | - -c 18 | - | 19 | curl -X POST "myes-node-0.myes-hs:9200/_snapshot/my_s3_repository/{{ .Params.RESTORE_SNAPSHOT_ID }}/_restore?pretty" 20 | -------------------------------------------------------------------------------- /unit1/operator/operator.yaml: -------------------------------------------------------------------------------- 1 | name: "myservice" 2 | version: "0.1.0" 3 | kudoVersion: 0.7.2 4 | kubernetesVersion: 1.15.0 5 | maintainers: 6 | - name: Michael Beisiegel 7 | email: michael.beisiegel@gmail.com 8 | url: https://github.com/realmbgl/kudo-tutorial 9 | tasks: 10 | deploy-task: 11 | resources: 12 | - config.yaml 13 | - pod.yaml 14 | plans: 15 | deploy: 16 | strategy: serial 17 | phases: 18 | - name: deploy-phase 19 | strategy: parallel 20 | steps: 21 | - name: deploy-step 22 | tasks: 23 | - deploy-task 24 | -------------------------------------------------------------------------------- /unit2/operator/operator.yaml: -------------------------------------------------------------------------------- 1 | name: "elastic" 2 | version: "0.1.0" 3 | kudoVersion: 0.7.2 4 | kubernetesVersion: 1.15.0 5 | appVersion: 7.0.0 6 | maintainers: 7 | - name: Michael Beisiegel 8 | email: michael.beisiegel@gmail.com 9 | url: https://github.com/realmbgl/kudo-tutorial 10 | tasks: 11 | deploy-task: 12 | resources: 13 | - service.yaml 14 | - node.yaml 15 | plans: 16 | deploy: 17 | strategy: serial 18 | phases: 19 | - name: deploy-phase 20 | strategy: parallel 21 | steps: 22 | - name: deploy-step 23 | tasks: 24 | - deploy-task 25 | -------------------------------------------------------------------------------- /unit4/operator/templates/backup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: {{ .PlanName }}-job 5 | namespace: default 6 | spec: 7 | template: 8 | metadata: 9 | name: {{ .PlanName }}-job 10 | spec: 11 | restartPolicy: OnFailure 12 | containers: 13 | - name: backup 14 | image: centos:7 15 | command: 16 | - sh 17 | - -c 18 | - | 19 | curl -X PUT "myes-node-0.myes-hs:9200/_snapshot/my_s3_repository" -H 'Content-Type: application/json' -d' 20 | { 21 | "type": "s3", 22 | "settings": { 23 | "bucket": "es-bucket", 24 | "endpoint": "{{ .Params.S3_ENDPOINT }}", 25 | "protocol": "http" 26 | } 27 | } 28 | '; 29 | TS=$(date +%s); 30 | curl -X PUT "myes-node-0.myes-hs:9200/_snapshot/my_s3_repository/snapshot_$TS?wait_for_completion=true&pretty" 31 | -------------------------------------------------------------------------------- /unit4/operator/operator.yaml: -------------------------------------------------------------------------------- 1 | name: "elastic" 2 | version: "0.1.0" 3 | kudoVersion: 0.7.2 4 | kubernetesVersion: 1.15.0 5 | appVersion: 7.0.0 6 | maintainers: 7 | - name: Michael Beisiegel 8 | email: michael.beisiegel@gmail.com 9 | url: https://github.com/realmbgl/kudo-tutorial 10 | tasks: 11 | deploy-task: 12 | resources: 13 | - service.yaml 14 | - node.yaml 15 | backup-task: 16 | resources: 17 | - backup.yaml 18 | restore-task: 19 | resources: 20 | - restore.yaml 21 | plans: 22 | deploy: 23 | strategy: serial 24 | phases: 25 | - name: deploy-phase 26 | strategy: parallel 27 | steps: 28 | - name: deploy-step 29 | tasks: 30 | - deploy-task 31 | backup: 32 | strategy: serial 33 | phases: 34 | - name: backup-phase 35 | strategy: serial 36 | steps: 37 | - name: backup-step 38 | tasks: 39 | - backup-task 40 | restore: 41 | strategy: serial 42 | phases: 43 | - name: restore-phase 44 | strategy: serial 45 | steps: 46 | - name: restore-step 47 | tasks: 48 | - restore-task 49 | -------------------------------------------------------------------------------- /unit3/operator/operator.yaml: -------------------------------------------------------------------------------- 1 | name: "elastic" 2 | version: "0.1.0" 3 | kudoVersion: 0.7.2 4 | kubernetesVersion: 1.15.0 5 | appVersion: 7.0.0 6 | maintainers: 7 | - name: Michael Beisiegel 8 | email: michael.beisiegel@gmail.com 9 | url: https://github.com/realmbgl/kudo-tutorial 10 | tasks: 11 | deploy-task: 12 | resources: 13 | - service.yaml 14 | - node.yaml 15 | update-task: 16 | resources: 17 | - service.yaml 18 | - node.yaml 19 | upgrade-task: 20 | resources: 21 | - service.yaml 22 | - node.yaml 23 | super-task: 24 | resources: 25 | - service.yaml 26 | - node.yaml 27 | plans: 28 | deploy: 29 | strategy: serial 30 | phases: 31 | - name: deploy-phase 32 | strategy: parallel 33 | steps: 34 | - name: deploy-step 35 | tasks: 36 | - deploy-task 37 | update: 38 | strategy: serial 39 | phases: 40 | - name: update-phase 41 | strategy: parallel 42 | steps: 43 | - name: update-step 44 | tasks: 45 | - update-task 46 | upgrade: 47 | strategy: serial 48 | phases: 49 | - name: upgrade-phase 50 | strategy: parallel 51 | steps: 52 | - name: upgrade-step 53 | tasks: 54 | - upgrade-task 55 | super: 56 | strategy: serial 57 | phases: 58 | - name: super-phase 59 | strategy: parallel 60 | steps: 61 | - name: super-step 62 | tasks: 63 | - super-task 64 | -------------------------------------------------------------------------------- /unit3/operator-next/operator.yaml: -------------------------------------------------------------------------------- 1 | name: "elastic" 2 | version: "0.2.0" 3 | kudoVersion: 0.7.2 4 | kubernetesVersion: 1.15.0 5 | appVersion: 7.2.0 6 | maintainers: 7 | - name: Michael Beisiegel 8 | email: michael.beisiegel@gmail.com 9 | url: https://github.com/realmbgl/kudo-tutorial 10 | tasks: 11 | deploy-task: 12 | resources: 13 | - service.yaml 14 | - node.yaml 15 | update-task: 16 | resources: 17 | - service.yaml 18 | - node.yaml 19 | upgrade-task: 20 | resources: 21 | - service.yaml 22 | - node.yaml 23 | super-task: 24 | resources: 25 | - service.yaml 26 | - node.yaml 27 | plans: 28 | deploy: 29 | strategy: serial 30 | phases: 31 | - name: deploy-phase 32 | strategy: parallel 33 | steps: 34 | - name: deploy-step 35 | tasks: 36 | - deploy-task 37 | update: 38 | strategy: serial 39 | phases: 40 | - name: update-phase 41 | strategy: parallel 42 | steps: 43 | - name: update-step 44 | tasks: 45 | - update-task 46 | upgrade: 47 | strategy: serial 48 | phases: 49 | - name: upgrade-phase 50 | strategy: parallel 51 | steps: 52 | - name: upgrade-step 53 | tasks: 54 | - upgrade-task 55 | super: 56 | strategy: serial 57 | phases: 58 | - name: super-phase 59 | strategy: parallel 60 | steps: 61 | - name: super-step 62 | tasks: 63 | - super-task 64 | -------------------------------------------------------------------------------- /unit2/operator/templates/node.yaml: -------------------------------------------------------------------------------- 1 | kind: StatefulSet 2 | apiVersion: apps/v1 3 | metadata: 4 | name: node 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: elastic # has to match .spec.template.metadata.labels 10 | serviceName: {{ .Name }}-hs 11 | replicas: {{ .Params.NODE_COUNT }} 12 | template: 13 | metadata: 14 | labels: 15 | app: elastic # has to match .spec.selector.matchLabels 16 | spec: 17 | initContainers: 18 | - name: init-sysctl 19 | image: busybox 20 | command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144'] 21 | securityContext: 22 | privileged: true 23 | - name: volume-permissions 24 | image: busybox 25 | command: ['sh', '-c', 'chown -R 1000:1000 /usr/share/elasticsearch/data'] 26 | volumeMounts: 27 | - name: data 28 | mountPath: /usr/share/elasticsearch/data 29 | terminationGracePeriodSeconds: 10 30 | containers: 31 | - name: elastic 32 | image: elasticsearch:7.0.0 33 | ports: 34 | - containerPort: 9200 35 | name: api 36 | - containerPort: 9300 37 | name: 38 | env: 39 | - name: cluster.name 40 | value: {{ .Name }}-cluster 41 | - name: discovery.seed_hosts 42 | value: {{ .Name }}-node-0.{{ .Name }}-hs,{{ .Name }}-node-1.{{ .Name }}-hs,{{ .Name }}-node-2.{{ .Name }}-hs 43 | - name: cluster.initial_master_nodes 44 | value: {{ .Name }}-node-0,{{ .Name }}-node-1,{{ .Name }}-node-2 45 | volumeMounts: 46 | - name: data 47 | mountPath: /usr/share/elasticsearch/data 48 | volumeClaimTemplates: 49 | - metadata: 50 | name: data 51 | spec: 52 | accessModes: [ "ReadWriteOnce" ] 53 | resources: 54 | requests: 55 | storage: 1Gi 56 | -------------------------------------------------------------------------------- /unit3/operator/templates/node.yaml: -------------------------------------------------------------------------------- 1 | kind: StatefulSet 2 | apiVersion: apps/v1 3 | metadata: 4 | name: node 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: elastic # has to match .spec.template.metadata.labels 10 | serviceName: {{ .Name }}-hs 11 | replicas: {{ .Params.NODE_COUNT }} 12 | template: 13 | metadata: 14 | labels: 15 | app: elastic # has to match .spec.selector.matchLabels 16 | spec: 17 | initContainers: 18 | - name: init-sysctl 19 | image: busybox 20 | command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144'] 21 | securityContext: 22 | privileged: true 23 | - name: volume-permissions 24 | image: busybox 25 | command: ['sh', '-c', 'chown -R 1000:1000 /usr/share/elasticsearch/data'] 26 | volumeMounts: 27 | - name: data 28 | mountPath: /usr/share/elasticsearch/data 29 | terminationGracePeriodSeconds: 10 30 | containers: 31 | - name: elastic 32 | image: elasticsearch:7.0.0 33 | ports: 34 | - containerPort: 9200 35 | name: api 36 | - containerPort: 9300 37 | name: 38 | env: 39 | - name: cluster.name 40 | value: {{ .Name }}-cluster 41 | - name: discovery.seed_hosts 42 | value: {{ .Name }}-node-0.{{ .Name }}-hs,{{ .Name }}-node-1.{{ .Name }}-hs,{{ .Name }}-node-2.{{ .Name }}-hs 43 | - name: cluster.initial_master_nodes 44 | value: {{ .Name }}-node-0,{{ .Name }}-node-1,{{ .Name }}-node-2 45 | volumeMounts: 46 | - name: data 47 | mountPath: /usr/share/elasticsearch/data 48 | volumeClaimTemplates: 49 | - metadata: 50 | name: data 51 | spec: 52 | accessModes: [ "ReadWriteOnce" ] 53 | resources: 54 | requests: 55 | storage: 1Gi 56 | -------------------------------------------------------------------------------- /unit3/operator-next/templates/node.yaml: -------------------------------------------------------------------------------- 1 | kind: StatefulSet 2 | apiVersion: apps/v1 3 | metadata: 4 | name: node 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: elastic # has to match .spec.template.metadata.labels 10 | serviceName: {{ .Name }}-hs 11 | replicas: {{ .Params.NODE_COUNT }} 12 | template: 13 | metadata: 14 | labels: 15 | app: elastic # has to match .spec.selector.matchLabels 16 | spec: 17 | initContainers: 18 | - name: init-sysctl 19 | image: busybox 20 | command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144'] 21 | securityContext: 22 | privileged: true 23 | - name: volume-permissions 24 | image: busybox 25 | command: ['sh', '-c', 'chown -R 1000:1000 /usr/share/elasticsearch/data'] 26 | volumeMounts: 27 | - name: data 28 | mountPath: /usr/share/elasticsearch/data 29 | terminationGracePeriodSeconds: 10 30 | containers: 31 | - name: elastic 32 | image: elasticsearch:7.2.0 33 | ports: 34 | - containerPort: 9200 35 | name: api 36 | - containerPort: 9300 37 | name: 38 | env: 39 | - name: cluster.name 40 | value: {{ .Name }}-cluster 41 | - name: discovery.seed_hosts 42 | value: {{ .Name }}-node-0.{{ .Name }}-hs,{{ .Name }}-node-1.{{ .Name }}-hs,{{ .Name }}-node-2.{{ .Name }}-hs 43 | - name: cluster.initial_master_nodes 44 | value: {{ .Name }}-node-0,{{ .Name }}-node-1,{{ .Name }}-node-2 45 | volumeMounts: 46 | - name: data 47 | mountPath: /usr/share/elasticsearch/data 48 | volumeClaimTemplates: 49 | - metadata: 50 | name: data 51 | spec: 52 | accessModes: [ "ReadWriteOnce" ] 53 | resources: 54 | requests: 55 | storage: 1Gi 56 | -------------------------------------------------------------------------------- /unit4/operator/templates/node.yaml: -------------------------------------------------------------------------------- 1 | kind: StatefulSet 2 | apiVersion: apps/v1 3 | metadata: 4 | name: node 5 | namespace: {{ .Namespace }} 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: elastic # has to match .spec.template.metadata.labels 10 | serviceName: {{ .Name }}-hs 11 | replicas: {{ .Params.NODE_COUNT }} 12 | template: 13 | metadata: 14 | labels: 15 | app: elastic # has to match .spec.selector.matchLabels 16 | spec: 17 | initContainers: 18 | - name: init-sysctl 19 | image: busybox 20 | command: ['sh', '-c', 'sysctl -w vm.max_map_count=262144'] 21 | securityContext: 22 | privileged: true 23 | - name: volume-permissions 24 | image: busybox 25 | command: ['sh', '-c', 'chown -R 1000:1000 /usr/share/elasticsearch/data'] 26 | volumeMounts: 27 | - name: data 28 | mountPath: /usr/share/elasticsearch/data 29 | terminationGracePeriodSeconds: 10 30 | containers: 31 | - name: elastic 32 | image: elasticsearch:7.0.0 33 | command: 34 | - sh 35 | - -c 36 | - | 37 | /usr/share/elasticsearch/bin/elasticsearch-plugin install repository-s3 -b; 38 | /usr/share/elasticsearch/bin/elasticsearch-keystore create 39 | echo {{ .Params.S3_ACCESS_KEY }} | /usr/share/elasticsearch/bin/elasticsearch-keystore add --stdin s3.client.default.access_key; 40 | echo {{ .Params.S3_SECRET_KEY }} | /usr/share/elasticsearch/bin/elasticsearch-keystore add --stdin s3.client.default.secret_key; 41 | /usr/local/bin/docker-entrypoint.sh eswrapper 42 | ports: 43 | - containerPort: 9200 44 | name: api 45 | - containerPort: 9300 46 | name: 47 | env: 48 | - name: cluster.name 49 | value: {{ .Name }}-cluster 50 | - name: discovery.seed_hosts 51 | value: {{ .Name }}-node-0.{{ .Name }}-hs,{{ .Name }}-node-1.{{ .Name }}-hs,{{ .Name }}-node-2.{{ .Name }}-hs 52 | - name: cluster.initial_master_nodes 53 | value: {{ .Name }}-node-0,{{ .Name }}-node-1,{{ .Name }}-node-2 54 | volumeMounts: 55 | - name: data 56 | mountPath: /usr/share/elasticsearch/data 57 | volumeClaimTemplates: 58 | - metadata: 59 | name: data 60 | spec: 61 | accessModes: [ "ReadWriteOnce" ] 62 | resources: 63 | requests: 64 | storage: 1Gi 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kudo tutorial 2 | 3 | 4 | 5 | Developing `Kubernetes` operators using `KUDO`, the Kubernetes Universal Declarative Operator. KUDO provides a declarative approach to building production-grade Kubernetes Operators covering the entire application lifecycle. 6 | 7 | ## install kudo 8 | 9 | Kudo comes with its own `kubectl CLI plugin`. On `Mac OS X` you can install it using `brew`. 10 | 11 | ``` 12 | brew tap kudobuilder/tap 13 | brew install kudo-cli 14 | ``` 15 | 16 | More on the kudo CLI at [kudo.dev](https://kudo.dev/docs/cli/) . 17 | 18 | Once you have a running `kubernetes` cluster with `kubectl` installed along with the KUDO CLI plugin, you can install kudo as follows. 19 | 20 | ``` 21 | kubectl kudo init 22 | ``` 23 | 24 | More on the kudo install at [kudo.dev](https://kudo.dev/docs/getting-started/) . 25 | 26 | 27 | ## install and operate kudo operators 28 | 29 | Install and operate your first kudo operator using [kafka](https://github.com/kudobuilder/operators/blob/master/repository/kafka/docs/v0.2/install.md) as the sample. 30 | 31 | 32 | ## develop kudo operators 33 | 34 | ### kudo operator programming model 35 | 36 | As a developer of a kudo operator you have to author three types of `YAML` artifacts in the following file folder structure. 37 | 38 | ``` 39 | operator.yaml 40 | params.yaml 41 | templates/ 42 |