From ef7f5ff5041ac0cc462a44c7bab86ed7c81a02bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Sep 2024 00:56:38 +0000 Subject: [PATCH] Added chart versions: cockroach-labs/cockroachdb: - 14.0.3 dynatrace/dynatrace-operator: - 1.3.0 speedscale/speedscale-operator: - 2.2.425 --- assets/cockroach-labs/cockroachdb-14.0.3.tgz | Bin 0 -> 32039 bytes assets/dynatrace/dynatrace-operator-1.3.0.tgz | Bin 0 -> 56455 bytes .../speedscale-operator-2.2.425.tgz | Bin 0 -> 16998 bytes .../cockroachdb/14.0.3/CONTRIBUTING.md | 14 + .../cockroachdb/14.0.3/Chart.yaml | 18 + .../cockroachdb/14.0.3/README.md | 588 ++ .../cockroachdb/14.0.3/app-readme.md | 9 + .../cockroachdb/14.0.3/templates/NOTES.txt | 50 + .../cockroachdb/14.0.3/templates/_helpers.tpl | 291 + .../14.0.3/templates/backendconfig.yaml | 21 + .../14.0.3/templates/certificate.ca.yaml | 33 + .../14.0.3/templates/certificate.client.yaml | 40 + .../14.0.3/templates/certificate.issuer.yaml | 20 + .../14.0.3/templates/certificate.node.yaml | 50 + .../14.0.3/templates/clusterrole.yaml | 19 + .../14.0.3/templates/clusterrolebinding.yaml | 23 + .../templates/cronjob-ca-certSelfSigner.yaml | 62 + .../cronjob-client-node-certSelfSigner.yaml | 69 + .../cockroachdb/14.0.3/templates/ingress.yaml | 90 + .../14.0.3/templates/job-certSelfSigner.yaml | 83 + .../14.0.3/templates/job-cleaner.yaml | 70 + .../14.0.3/templates/job.init.yaml | 303 + .../14.0.3/templates/networkpolicy.yaml | 59 + .../14.0.3/templates/poddisruptionbudget.yaml | 26 + .../templates/role-certRotateSelfSigner.yaml | 27 + .../14.0.3/templates/role-certSelfSigner.yaml | 33 + .../cockroachdb/14.0.3/templates/role.yaml | 23 + .../rolebinding-certRotateSelfSigner.yaml | 23 + .../templates/rolebinding-certSelfSigner.yaml | 29 + .../14.0.3/templates/rolebinding.yaml | 23 + .../templates/secret.backendconfig.yaml | 25 + .../14.0.3/templates/secret.logconfig.yaml | 19 + .../14.0.3/templates/secret.registry.yaml | 23 + .../14.0.3/templates/secrets.init.yaml | 20 + .../14.0.3/templates/service.discovery.yaml | 64 + .../14.0.3/templates/service.public.yaml | 55 + .../14.0.3/templates/serviceMonitor.yaml | 54 + .../serviceaccount-certRotateSelfSigner.yaml | 22 + .../serviceaccount-certSelfSigner.yaml | 25 + .../14.0.3/templates/serviceaccount.yaml | 21 + .../14.0.3/templates/statefulset.yaml | 402 ++ .../14.0.3/templates/tests/client.yaml | 65 + .../cockroachdb/14.0.3/values.schema.json | 97 + .../cockroachdb/14.0.3/values.yaml | 606 ++ .../dynatrace-operator/1.3.0/.helmignore | 25 + .../dynatrace-operator/1.3.0/Chart.yaml | 23 + .../dynatrace-operator/1.3.0/README.md | 48 + .../dynatrace-operator/1.3.0/app-readme.md | 5 + .../dynatrace-operator/1.3.0/logo.png | Bin 0 -> 9908 bytes .../dynatrace-operator/1.3.0/questions.yml | 236 + .../activegate/clusterrole-activegate.yaml | 47 + .../activegate/serviceaccount-activegate.yaml | 20 + .../Common/crd/dynatrace-operator-crd.yaml | 5783 +++++++++++++++++ .../templates/Common/csi/clusterrole-csi.yaml | 47 + .../1.3.0/templates/Common/csi/csidriver.yaml | 29 + .../1.3.0/templates/Common/csi/daemonset.yaml | 280 + .../templates/Common/csi/priority-class.yaml | 23 + .../1.3.0/templates/Common/csi/role-csi.yaml | 70 + .../Common/csi/serviceaccount-csi.yaml | 22 + .../edge-connect/serviceaccount-operator.yaml | 20 + .../clusterrole-kubernetes-monitoring.yaml | 114 + .../serviceaccount-kubernetes-monitoring.yaml | 20 + .../Common/oneagent/clusterrole-oneagent.yaml | 45 + .../oneagent/serviceaccount-oneagent.yaml | 21 + .../Common/operator/clusterrole-operator.yaml | 109 + .../Common/operator/deployment-operator.yaml | 111 + .../Common/operator/role-operator.yaml | 170 + .../operator/serviceaccount-operator.yaml | 20 + .../Common/webhook/clusterrole-webhook.yaml | 102 + .../Common/webhook/deployment-webhook.yaml | 138 + .../webhook/mutatingwebhookconfiguration.yaml | 58 + .../webhook/poddisruptionbudget-webhook.yaml | 11 + .../Common/webhook/role-webhook.yaml | 70 + .../templates/Common/webhook/service.yaml | 27 + .../webhook/serviceaccount-webhook.yaml | 21 + .../validatingwebhookconfiguration.yaml | 104 + .../1.3.0/templates/NOTES.txt | 10 + .../1.3.0/templates/_csidriver.tpl | 74 + .../1.3.0/templates/_helpers.tpl | 53 + .../1.3.0/templates/_labels.tpl | 102 + .../1.3.0/templates/_platform.tpl | 84 + .../1.3.0/templates/application.yaml | 98 + .../dynatrace-operator/1.3.0/values.yaml | 196 + .../speedscale-operator/2.2.425/.helmignore | 23 + .../speedscale-operator/2.2.425/Chart.yaml | 27 + .../speedscale-operator/2.2.425/LICENSE | 201 + .../speedscale-operator/2.2.425/README.md | 111 + .../speedscale-operator/2.2.425/app-readme.md | 111 + .../2.2.425/questions.yaml | 9 + .../2.2.425/templates/NOTES.txt | 12 + .../2.2.425/templates/admission.yaml | 209 + .../2.2.425/templates/configmap.yaml | 43 + .../templates/crds/trafficreplays.yaml | 523 ++ .../2.2.425/templates/deployments.yaml | 132 + .../2.2.425/templates/hooks.yaml | 73 + .../2.2.425/templates/rbac.yaml | 244 + .../2.2.425/templates/secrets.yaml | 18 + .../2.2.425/templates/services.yaml | 22 + .../2.2.425/templates/tls.yaml | 183 + .../speedscale-operator/2.2.425/values.yaml | 138 + index.yaml | 82 +- 101 files changed, 14190 insertions(+), 1 deletion(-) create mode 100644 assets/cockroach-labs/cockroachdb-14.0.3.tgz create mode 100644 assets/dynatrace/dynatrace-operator-1.3.0.tgz create mode 100644 assets/speedscale/speedscale-operator-2.2.425.tgz create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/CONTRIBUTING.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/Chart.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/README.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/app-readme.md create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/NOTES.txt create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/_helpers.tpl create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/backendconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.ca.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.client.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.issuer.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.node.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrole.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrolebinding.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-ca-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-client-node-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/ingress.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/job-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/job-cleaner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/job.init.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/networkpolicy.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/poddisruptionbudget.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/role.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.backendconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.logconfig.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.registry.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/secrets.init.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/service.discovery.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/service.public.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceMonitor.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certRotateSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certSelfSigner.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/statefulset.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/templates/tests/client.yaml create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/values.schema.json create mode 100644 charts/cockroach-labs/cockroachdb/14.0.3/values.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/.helmignore create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/Chart.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/README.md create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/app-readme.md create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/logo.png create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/questions.yml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/clusterrole-activegate.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/serviceaccount-activegate.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/crd/dynatrace-operator-crd.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/clusterrole-csi.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/csidriver.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/daemonset.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/priority-class.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/role-csi.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/serviceaccount-csi.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/edge-connect/serviceaccount-operator.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/clusterrole-oneagent.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/serviceaccount-oneagent.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/clusterrole-operator.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/deployment-operator.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/role-operator.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/serviceaccount-operator.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/clusterrole-webhook.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/deployment-webhook.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/mutatingwebhookconfiguration.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/poddisruptionbudget-webhook.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/role-webhook.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/service.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/serviceaccount-webhook.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/validatingwebhookconfiguration.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/NOTES.txt create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/_csidriver.tpl create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/_helpers.tpl create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/_labels.tpl create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/_platform.tpl create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/templates/application.yaml create mode 100644 charts/dynatrace/dynatrace-operator/1.3.0/values.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/.helmignore create mode 100644 charts/speedscale/speedscale-operator/2.2.425/Chart.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/LICENSE create mode 100644 charts/speedscale/speedscale-operator/2.2.425/README.md create mode 100644 charts/speedscale/speedscale-operator/2.2.425/app-readme.md create mode 100644 charts/speedscale/speedscale-operator/2.2.425/questions.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/NOTES.txt create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/admission.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/configmap.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/crds/trafficreplays.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/deployments.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/hooks.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/rbac.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/secrets.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/services.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/templates/tls.yaml create mode 100644 charts/speedscale/speedscale-operator/2.2.425/values.yaml diff --git a/assets/cockroach-labs/cockroachdb-14.0.3.tgz b/assets/cockroach-labs/cockroachdb-14.0.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..96ef59a2d0658d81da7b401c657f289967839ce2 GIT binary patch literal 32039 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,#Kft|QjobHe(mZ>;D7hi%5PmA-Th+5nDm$pvs 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 J<&gkX0RV)$Dy{$k literal 0 HcmV?d00001 diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/CONTRIBUTING.md b/charts/cockroach-labs/cockroachdb/14.0.3/CONTRIBUTING.md new file mode 100644 index 0000000000..e248d72e11 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +Contributions are welcome! + +For every change, please increment the `version` contained in +[Chart.yaml](https://github.com/cockroachdb/helm-charts/blob/master/cockroachdb/Chart.yaml). +The `version` roughly follows the [SEMVER](https://semver.org/) versioning +pattern. For changes which do not affect backwards compatibility, the PATCH or +MINOR version must be incremented, e.g. `4.1.3` -> `4.1.4`. For changes which +affect the backwards compatibility of the chart, the major version must be +incremented, e.g. `4.1.3` -> `5.0.0`. Examples of changes which affect backwards +compatibility include any major version releases of CockroachDB, as well as any +breaking changes to the CockroachDB chart templates. + diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/Chart.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/Chart.yaml new file mode 100644 index 0000000000..4cb8644a53 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/Chart.yaml @@ -0,0 +1,18 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: CockroachDB + catalog.cattle.io/kube-version: '>=1.8-0' + catalog.cattle.io/release-name: cockroachdb +apiVersion: v1 +appVersion: 24.2.2 +description: CockroachDB is a scalable, survivable, strongly-consistent SQL database. +home: https://www.cockroachlabs.com +icon: file://assets/icons/cockroachdb.png +kubeVersion: '>=1.8-0' +maintainers: +- email: helm-charts@cockroachlabs.com + name: cockroachlabs +name: cockroachdb +sources: +- https://github.com/cockroachdb/cockroach +version: 14.0.3 diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/README.md b/charts/cockroach-labs/cockroachdb/14.0.3/README.md new file mode 100644 index 0000000000..6187c99847 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/README.md @@ -0,0 +1,588 @@ + +# CockroachDB Helm Chart + +[CockroachDB](https://github.com/cockroachdb/cockroach) - the open source, cloud-native distributed SQL database. + +## Documentation + +Below is a brief overview of operating the CockroachDB Helm Chart and some specific implementation details. For additional information on deploying CockroachDB, please see: +> + +Note that the documentation requires Helm 3.0 or higher. + +## Prerequisites Details + +* Kubernetes 1.8 +* PV support on the underlying infrastructure (only if using `storage.persistentVolume`). [Docker for windows hostpath provisioner is not supported](https://github.com/cockroachdb/docs/issues/3184). +* If you want to secure your cluster to use TLS certificates for all network communication, [Helm must be installed with RBAC privileges](https://helm.sh/docs/topics/rbac/) or else you will get an "attempt to grant extra privileges" error. + +## StatefulSet Details + +* + +## StatefulSet Caveats + +* + +## Chart Details + +This chart will do the following: + +* Set up a dynamically scalable CockroachDB cluster using a Kubernetes StatefulSet. + +## Add the CockroachDB Repository + +```shell +helm repo add cockroachdb https://charts.cockroachdb.com/ +``` + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```shell +helm install my-release cockroachdb/cockroachdb +``` + +Note that for a production cluster, you will likely want to override the following parameters in [`values.yaml`](values.yaml) with your own values. + +- `statefulset.resources.requests.memory` and `statefulset.resources.limits.memory` allocate memory resources to CockroachDB pods in your cluster. +- `conf.cache` and `conf.max-sql-memory` are memory limits that we recommend setting to 1/4 of the above resource allocation. When running CockroachDB, you must set these limits explicitly to avoid running out of memory. +- `storage.persistentVolume.size` defaults to `100Gi` of disk space per pod, which you may increase or decrease for your use case. +- `storage.persistentVolume.storageClass` uses the default storage class for your environment. We strongly recommend that you specify a storage class which uses an SSD. +- `tls.enabled` must be set to `yes`/`true` to deploy in secure mode. + +For more information on overriding the `values.yaml` parameters, please see: +> + +Confirm that all pods are `Running` successfully and init has been completed: + +```shell +kubectl get pods +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 1m +my-release-cockroachdb-1 1/1 Running 0 1m +my-release-cockroachdb-2 1/1 Running 0 1m +my-release-cockroachdb-init-k6jcr 0/1 Completed 0 1m +``` + +Confirm that persistent volumes are created and claimed for each pod: + +```shell +kubectl get pv +``` + +``` +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE +pvc-64878ebf-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-0 standard 51s +pvc-64945b4f-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-1 standard 51s +pvc-649d920d-f3f0-11e8-ab5b-42010a8e0035 100Gi RWO Delete Bound default/datadir-my-release-cockroachdb-2 standard 51s +``` + +### Running in secure mode + +In order to set up a secure cockroachdb cluster set `tls.enabled` to `yes`/`true` + +There are 3 ways to configure a secure cluster, with this chart. This all relates to how the certificates are issued: + +* Self-signer (default) +* Cert-manager +* Manual + +#### Self-signer + +This is the default behaviour, and requires no configuration beyond setting certificate durations if user wants to set custom duration. + +If you are running in this mode, self-signed certificates are created by self-signed utility for the nodes and root client and are stored in a secret. +You can look for the certificates created: +```shell +kubectl get secrets +``` + +```shell +crdb-cockroachdb-ca-secret Opaque 2 23s +crdb-cockroachdb-client-secret kubernetes.io/tls 3 22s +crdb-cockroachdb-node-secret kubernetes.io/tls 3 23s +``` + + +#### Manual + +If you wish to supply the certificates to the nodes yourself set `tls.certs.provided` to `yes`/`true`. You may want to use this if you want to use a different certificate authority from the one being used by Kubernetes or if your Kubernetes cluster doesn't fully support certificate-signing requests. To use this, first set up your certificates and load them into your Kubernetes cluster as Secrets using the commands below: + +```shell +$ mkdir certs +$ mkdir my-safe-directory +$ cockroach cert create-ca --certs-dir=certs --ca-key=my-safe-directory/ca.key +$ cockroach cert create-client root --certs-dir=certs --ca-key=my-safe-directory/ca.key +$ kubectl create secret generic cockroachdb-root --from-file=certs +secret/cockroachdb-root created +$ cockroach cert create-node --certs-dir=certs --ca-key=my-safe-directory/ca.key localhost 127.0.0.1 my-release-cockroachdb-public my-release-cockroachdb-public.my-namespace my-release-cockroachdb-public.my-namespace.svc.cluster.local *.my-release-cockroachdb *.my-release-cockroachdb.my-namespace *.my-release-cockroachdb.my-namespace.svc.cluster.local +$ kubectl create secret generic cockroachdb-node --from-file=certs +secret/cockroachdb-node created +``` + +> Note: The subject alternative names are based on a release called `my-release` in the `my-namespace` namespace. Make sure they match the services created with the release during `helm install` + +If your certificates are stored in tls secrets such as secrets generated by cert-manager, the secret will contain files named: + +* `ca.crt` +* `tls.crt` +* `tls.key` + +Cockroachdb, however, expects the files to be named like this: + +* `ca.crt` +* `node.crt` +* `node.key` +* `client.root.crt` +* `client.root.key` + +By enabling `tls.certs.tlsSecret` the tls secrets are projected on to the correct filenames, when they are mounted to the cockroachdb pods. + +#### Cert-manager + +If you wish to supply certificates with [cert-manager][3], set + +* `tls.certs.certManager` to `yes`/`true` +* `tls.certs.certManagerIssuer` to an IssuerRef (as they appear in certificate resources) pointing to a clusterIssuer or issuer, you have set up in the cluster + +Example issuer: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: cockroachdb-ca + namespace: cockroachdb +data: + tls.crt: [BASE64 Encoded ca.crt] + tls.key: [BASE64 Encoded ca.key] +type: kubernetes.io/tls +--- +apiVersion: cert-manager.io/v1alpha3 +kind: Issuer +metadata: + name: cockroachdb-cert-issuer + namespace: cockroachdb +spec: + ca: + secretName: cockroachdb-ca +``` + +## Upgrading the cluster + +### Chart version 3.0.0 and after + +Launch a temporary interactive pod and start the built-in SQL client: + +```shell +kubectl run cockroachdb --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host=my-release-cockroachdb-public +``` + +> If you are running in secure mode, you will have to provide a client certificate to the cluster in order to authenticate, so the above command will not work. See [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/client-secure.yaml) for an example of how to set up an interactive SQL shell against a secure cluster or [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/example-app-secure.yaml) for an example application connecting to a secure cluster. + +Set `cluster.preserve_downgrade_option`, where `$current_version` is the CockroachDB version currently running (e.g., `19.2`): + +```sql +> SET CLUSTER SETTING cluster.preserve_downgrade_option = '$current_version'; +``` + +Exit the shell and delete the temporary pod: + +```sql +> \q +``` + +Kick off the upgrade process by changing the new Docker image, where `$new_version` is the CockroachDB version to which you are upgrading: + +```shell +helm upgrade my-release cockroachdb/cockroachdb \ +--set image.tag=$new_version \ +--reuse-values +``` + +Kubernetes will carry out a safe [rolling upgrade](https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/#updating-statefulsets) of your CockroachDB nodes one-by-one. Monitor the cluster's pods until all have been successfully restarted: + +```shell +kubectl get pods +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 2m +my-release-cockroachdb-1 1/1 Running 0 3m +my-release-cockroachdb-2 1/1 Running 0 3m +my-release-cockroachdb-3 0/1 ContainerCreating 0 25s +my-release-cockroachdb-init-nwjkh 0/1 ContainerCreating 0 6s +``` + +```shell +kubectl get pods \ +-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\n"}' +``` + +``` +my-release-cockroachdb-0 cockroachdb/cockroach:v24.2.2 +my-release-cockroachdb-1 cockroachdb/cockroach:v24.2.2 +my-release-cockroachdb-2 cockroachdb/cockroach:v24.2.2 +my-release-cockroachdb-3 cockroachdb/cockroach:v24.2.2 +``` + +Resume normal operations. Once you are comfortable that the stability and performance of the cluster is what you'd expect post-upgrade, finalize the upgrade: + +```shell +kubectl run cockroachdb --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host=my-release-cockroachdb-public +``` + +```sql +> RESET CLUSTER SETTING cluster.preserve_downgrade_option; +> \q +``` + +### Chart versions prior to 3.0.0 + +Due to a change in the label format in version 3.0.0 of this chart, upgrading requires that you delete the StatefulSet. Luckily there is a way to do it without actually deleting all the resources managed by the StatefulSet. Use the workaround below to upgrade from charts versions previous to 3.0.0: + +Get the new labels from the specs rendered by Helm: + +```shell +helm template -f deploy.vals.yml cockroachdb/cockroachdb -x templates/statefulset.yaml \ +| yq r - spec.template.metadata.labels +``` + +``` +app.kubernetes.io/name: cockroachdb +app.kubernetes.io/instance: my-release +app.kubernetes.io/component: cockroachdb +``` + +Place the new labels on all pods of the StatefulSet (change `my-release-cockroachdb-0` to the name of each pod): + +```shell +kubectl label pods my-release-cockroachdb-0 \ +app.kubernetes.io/name=cockroachdb \ +app.kubernetes.io/instance=my-release \ +app.kubernetes.io/component=cockroachdb +``` + +Delete the StatefulSet without deleting pods: + +```shell +kubectl delete statefulset my-release-cockroachdb --cascade=false +``` + +Verify that no pod is deleted and then upgrade as normal. A new StatefulSet will be created, taking over the management of the existing pods and upgrading them if needed. + +### See also + +For more information about upgrading a cluster to the latest major release of CockroachDB, see [Upgrade to CockroachDB](https://www.cockroachlabs.com/docs/stable/upgrade-cockroach-version.html). + +Note that there are sometimes backward-incompatible changes to SQL features between major CockroachDB releases. For details, see the [Upgrade Policy](https://www.cockroachlabs.com/docs/cockroachcloud/upgrade-policy). + +## Configuration + +The following table lists the configurable parameters of the CockroachDB chart and their default values. +For details see the [`values.yaml`](values.yaml) file. + +| Parameter | Description | Default | +| --------- | ----------- | ------- | +| `clusterDomain` | Cluster's default DNS domain | `cluster.local` | +| `conf.attrs` | CockroachDB node attributes | `[]` | +| `conf.cache` | Size of CockroachDB's in-memory cache | `25%` | +| `conf.cluster-name` | Name of CockroachDB cluster | `""` | +| `conf.disable-cluster-name-verification` | Disable CockroachDB cluster name verification | `no` | +| `conf.join` | List of already-existing CockroachDB instances | `[]` | +| `conf.max-disk-temp-storage` | Max storage capacity for temp data | `0` | +| `conf.max-offset` | Max allowed clock offset for CockroachDB cluster | `500ms` | +| `conf.max-sql-memory` | Max memory to use processing SQL querie | `25%` | +| `conf.locality` | Locality attribute for this deployment | `""` | +| `conf.single-node` | Disable CockroachDB clustering (standalone mode) | `no` | +| `conf.sql-audit-dir` | Directory for SQL audit log | `""` | +| `conf.port` | CockroachDB primary serving port in Pods | `26257` | +| `conf.http-port` | CockroachDB HTTP port in Pods | `8080` | +| `conf.path` | CockroachDB data directory mount path | `cockroach-data` | +| `conf.store.enabled` | Enable store configuration for CockroachDB | `false` | +| `conf.store.type` | CockroachDB storage type | `""` | +| `conf.store.size` | CockroachDB storage size | `""` | +| `conf.store.attrs` | CockroachDB storage attributes | `""` | +| `image.repository` | Container image name | `cockroachdb/cockroach` | +| `image.tag` | Container image tag | `v24.2.2` | +| `image.pullPolicy` | Container pull policy | `IfNotPresent` | +| `image.credentials` | `registry`, `user` and `pass` credentials to pull private image | `{}` | +| `statefulset.replicas` | StatefulSet replicas number | `3` | +| `statefulset.updateStrategy` | Update strategy for StatefulSet Pods | `{"type": "RollingUpdate"}` | +| `statefulset.podManagementPolicy` | `OrderedReady`/`Parallel` Pods creation/deletion order | `Parallel` | +| `statefulset.budget.maxUnavailable` | k8s PodDisruptionBudget parameter | `1` | +| `statefulset.args` | Extra command-line arguments | `[]` | +| `statefulset.env` | Extra env vars | `[]` | +| `statefulset.secretMounts` | Additional Secrets to mount at cluster members | `[]` | +| `statefulset.labels` | Additional labels of StatefulSet and its Pods | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `statefulset.annotations` | Additional annotations of StatefulSet Pods | `{}` | +| `statefulset.nodeAffinity` | [Node affinity rules][2] of StatefulSet Pods | `{}` | +| `statefulset.podAffinity` | [Inter-Pod affinity rules][1] of StatefulSet Pods | `{}` | +| `statefulset.podAntiAffinity` | [Anti-affinity rules][1] of StatefulSet Pods | auto | +| `statefulset.podAntiAffinity.topologyKey` | The topologyKey for auto [anti-affinity rules][1] | `kubernetes.io/hostname` | +| `statefulset.podAntiAffinity.type` | Type of auto [anti-affinity rules][1] | `soft` | +| `statefulset.podAntiAffinity.weight` | Weight for `soft` auto [anti-affinity rules][1] | `100` | +| `statefulset.nodeSelector` | Node labels for StatefulSet Pods assignment | `{}` | +| `statefulset.priorityClassName` | [PriorityClassName][4] for StatefulSet Pods | `""` | +| `statefulset.tolerations` | Node taints to tolerate by StatefulSet Pods | `[]` | +| `statefulset.topologySpreadConstraints` | [Topology Spread Constraints rules][5] of StatefulSet Pods | auto | +| `statefulset.topologySpreadConstraints.maxSkew` | Degree to which Pods may be unevenly distributed | `1` | +| `statefulset.topologySpreadConstraints.topologyKey` | The key of node labels | `topology.kubernetes.io/zone` | +| `statefulset.topologySpreadConstraints.whenUnsatisfiable` | `ScheduleAnyway`/`DoNotSchedule` for unsatisfiable constraints | `ScheduleAnyway` | +| `statefulset.resources` | Resource requests and limits for StatefulSet Pods | `{}` | +| `statefulset.customLivenessProbe` | Custom Liveness probe | `{}` | +| `statefulset.customReadinessProbe` | Custom Rediness probe | `{}` | +| `statefulset.terminationGracePeriodSeconds` | Termination grace period for CRDB statefulset pods | `300` | +| `service.ports.grpc.external.port` | CockroachDB primary serving port in Services | `26257` | +| `service.ports.grpc.external.name` | CockroachDB primary serving port name in Services | `grpc` | +| `service.ports.grpc.internal.port` | CockroachDB inter-communication port in Services | `26257` | +| `service.ports.grpc.internal.name` | CockroachDB inter-communication port name in Services | `grpc-internal` | +| `service.ports.http.port` | CockroachDB HTTP port in Services | `8080` | +| `service.ports.http.name` | CockroachDB HTTP port name in Services | `http` | +| `service.public.type` | Public Service type | `ClusterIP` | +| `service.public.labels` | Additional labels of public Service | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `service.public.annotations` | Additional annotations of public Service | `{}` | +| `service.discovery.labels` | Additional labels of discovery Service | `{"app.kubernetes.io/component": "cockroachdb"}` | +| `service.discovery.annotations` | Additional annotations of discovery Service | `{}` | +| `ingress.enabled` | Enable ingress resource for CockroachDB | `false` | +| `ingress.labels` | Additional labels of Ingress | `{}` | +| `ingress.annotations` | Additional annotations of Ingress | `{}` | +| `ingress.paths` | Paths for the default host | `[/]` | +| `ingress.hosts` | CockroachDB Ingress hostnames | `[]` | +| `ingress.tls[0].hosts` | CockroachDB Ingress tls hostnames | `nil` | +| `ingress.tls[0].secretName` | CockroachDB Ingress tls secret name | `nil` | +| `prometheus.enabled` | Enable automatic monitoring of all instances when Prometheus is running | `true` | +| `serviceMonitor.enabled` | Create [ServiceMonitor](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/design.md#servicemonitor) Resource for scraping metrics using [PrometheusOperator](https://github.com/prometheus-operator/prometheus-operator/blob/master/Documentation/user-guides/getting-started.md#prometheus-operator) | `false` | +| `serviceMonitor.labels` | Additional labels of ServiceMonitor | `{}` | +| `serviceMonitor.annotations` | Additional annotations of ServiceMonitor | `{}` | +| `serviceMonitor.interval` | ServiceMonitor scrape metrics interval | `10s` | +| `serviceMonitor.scrapeTimeout` | ServiceMonitor scrape timeout | `nil` | +| `serviceMonitor.tlsConfig` | Additional TLS configuration of ServiceMonitor | `{}` | +| `serviceMonitor.namespaced` | Limit ServiceMonitor to current namespace | `false` | +| `storage.hostPath` | Absolute path on host to store data | `""` | +| `storage.persistentVolume.enabled` | Whether to use PersistentVolume to store data | `yes` | +| `storage.persistentVolume.size` | PersistentVolume size | `100Gi` | +| `storage.persistentVolume.storageClass` | PersistentVolume class | `""` | +| `storage.persistentVolume.labels` | Additional labels of PersistentVolumeClaim | `{}` | +| `storage.persistentVolume.annotations` | Additional annotations of PersistentVolumeClaim | `{}` | +| `init.labels` | Additional labels of init Job and its Pod | `{"app.kubernetes.io/component": "init"}` | +| `init.jobAnnotations` | Additional annotations of the init Job itself | `{}` | +| `init.annotations` | Additional annotations of the Pod of init Job | `{}` | +| `init.affinity` | [Affinity rules][2] of init Job Pod | `{}` | +| `init.nodeSelector` | Node labels for init Job Pod assignment | `{}` | +| `init.tolerations` | Node taints to tolerate by init Job Pod | `[]` | +| `init.resources` | Resource requests and limits for the `cluster-init` container | `{}` | +| `init.terminationGracePeriodSeconds` | Termination grace period for CRDB init job | `300` | +| `tls.enabled` | Whether to run securely using TLS certificates | `no` | +| `tls.serviceAccount.create` | Whether to create a new RBAC service account | `yes` | +| `tls.serviceAccount.name` | Name of RBAC service account to use | `""` | +| `tls.copyCerts.image` | Image used in copy certs init container | `busybox` | +| `tls.copyCerts.resources` | Resource requests and limits for the `copy-certs` container | `{}` | +| `tls.certs.provided` | Bring your own certs scenario, i.e certificates are provided | `no` | +| `tls.certs.clientRootSecret` | If certs are provided, secret name for client root cert | `cockroachdb-root` | +| `tls.certs.nodeSecret` | If certs are provided, secret name for node cert | `cockroachdb-node` | +| `tls.certs.tlsSecret` | Own certs are stored in TLS secret | `no` | +| `tls.certs.selfSigner.enabled` | Whether cockroachdb should generate its own self-signed certs | `true` | +| `tls.certs.selfSigner.caProvided` | Bring your own CA scenario. This CA will be used to generate node and client cert | `false` | +| `tls.certs.selfSigner.caSecret` | If CA is provided, secret name for CA cert | `""` | +| `tls.certs.selfSigner.minimumCertDuration` | Minimum cert duration for all the certs, all certs duration will be validated against this duration | `624h` | +| `tls.certs.selfSigner.caCertDuration` | Duration of CA cert in hour | `43824h` | +| `tls.certs.selfSigner.caCertExpiryWindow` | Expiry window of CA cert means a window before actual expiry in which CA cert should be rotated | `648h` | +| `tls.certs.selfSigner.clientCertDuration` | Duration of client cert in hour | `672h | +| `tls.certs.selfSigner.clientCertExpiryWindow` | Expiry window of client cert means a window before actual expiry in which client cert should be rotated | `48h` | +| `tls.certs.selfSigner.nodeCertDuration` | Duration of node cert in hour | `8760h` | +| `tls.certs.selfSigner.nodeCertExpiryWindow` | Expiry window of node cert means a window before actual expiry in which node certs should be rotated | `168h` | +| `tls.certs.selfSigner.rotateCerts` | Whether to rotate the certs generate by cockroachdb | `true` | +| `tls.certs.selfSigner.readinessWait` | Wait time for each cockroachdb replica to become ready once it comes in running state. Only considered when rotateCerts is set to true | `30s` | +| `tls.certs.selfSigner.podUpdateTimeout` | Wait time for each cockroachdb replica to get to running state. Only considered when rotateCerts is set to true | `2m` | +| `tls.certs.certManager` | Provision certificates with cert-manager | `false` | +| `tls.certs.certManagerIssuer.group` | IssuerRef group to use when generating certificates | `cert-manager.io` | +| `tls.certs.certManagerIssuer.kind` | IssuerRef kind to use when generating certificates | `Issuer` | +| `tls.certs.certManagerIssuer.name` | IssuerRef name to use when generating certificates | `cockroachdb` | +| `tls.certs.certManagerIssuer.caCertDuration` | Duration of CA cert in hour | `43824h` | +| `tls.certs.certManagerIssuer.caCertExpiryWindow` | Expiry window of CA cert means a window before actual expiry in which CA cert should be rotated | `648h` | +| `tls.certs.certManagerIssuer.clientCertDuration` | Duration of client cert in hours | `672h` | +| `tls.certs.certManagerIssuer.clientCertExpiryWindow` | Expiry window of client cert means a window before actual expiry in which client cert should be rotated | `48h` | +| `tls.certs.certManagerIssuer.nodeCertDuration` | Duration of node cert in hours | `8760h` | +| `tls.certs.certManagerIssuer.nodeCertExpiryWindow` | Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. | `168h` | +| `tls.selfSigner.image.repository` | Image to use for self signing TLS certificates | `cockroachlabs-helm-charts/cockroach-self-signer-cert`| +| `tls.selfSigner.image.tag` | Image tag to use for self signing TLS certificates | `0.1` | +| `tls.selfSigner.image.pullPolicy` | Self signing TLS certificates container pull policy | `IfNotPresent` | +| `tls.selfSigner.image.credentials` | `registry`, `user` and `pass` credentials to pull private image | `{}` | +| `networkPolicy.enabled` | Enable NetworkPolicy for CockroachDB's Pods | `no` | +| `networkPolicy.ingress.grpc` | Whitelist resources to access gRPC port of CockroachDB's Pods | `[]` | +| `networkPolicy.ingress.http` | Whitelist resources to access gRPC port of CockroachDB's Pods | `[]` | + + +Override the default parameters using the `--set key=value[,key=value]` argument to `helm install`. + +Alternatively, a YAML file that specifies custom values for the parameters can be provided while installing the chart. For example: + +```shell +helm install my-release -f my-values.yaml cockroachdb/cockroachdb +``` + +> **Tip**: You can use the default [values.yaml](values.yaml) + +## Deep dive + +### Connecting to the CockroachDB cluster + +Once you've created the cluster, you can start talking to it by connecting to its `-public` Service. CockroachDB is PostgreSQL wire protocol compatible, so there's a [wide variety of supported clients](https://www.cockroachlabs.com/docs/install-client-drivers.html). As an example, we'll open up a SQL shell using CockroachDB's built-in shell and play around with it a bit, like this (likely needing to replace `my-release-cockroachdb-public` with the name of the `-public` Service that was created with your installed chart): + +```shell +kubectl run cockroach-client --rm -it \ +--image=cockroachdb/cockroach \ +--restart=Never \ +-- sql --insecure --host my-release-cockroachdb-public +``` + +``` +Waiting for pod default/cockroach-client to be running, status is Pending, +pod ready: false +If you don't see a command prompt, try pressing enter. +root@my-release-cockroachdb-public:26257> SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| pg_catalog | +| system | ++--------------------+ +(3 rows) +root@my-release-cockroachdb-public:26257> CREATE DATABASE bank; +CREATE DATABASE +root@my-release-cockroachdb-public:26257> CREATE TABLE bank.accounts (id INT +PRIMARY KEY, balance DECIMAL); +CREATE TABLE +root@my-release-cockroachdb-public:26257> INSERT INTO bank.accounts VALUES +(1234, 10000.50); +INSERT 1 +root@my-release-cockroachdb-public:26257> SELECT * FROM bank.accounts; ++------+---------+ +| id | balance | ++------+---------+ +| 1234 | 10000.5 | ++------+---------+ +(1 row) +root@my-release-cockroachdb-public:26257> \q +Waiting for pod default/cockroach-client to terminate, status is Running +pod "cockroach-client" deleted +``` + +> If you are running in secure mode, you will have to provide a client certificate to the cluster in order to authenticate, so the above command will not work. See [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/client-secure.yaml) for an example of how to set up an interactive SQL shell against a secure cluster or [here](https://github.com/cockroachdb/cockroach/blob/master/cloud/kubernetes/example-app-secure.yaml) for an example application connecting to a secure cluster. + +### Cluster health + +Because our pod spec includes regular health checks of the CockroachDB processes, simply running `kubectl get pods` and looking at the `STATUS` column is sufficient to determine the health of each instance in the cluster. + +If you want more detailed information about the cluster, the best place to look is the Admin UI. + +### Accessing the Admin UI + +If you want to see information about how the cluster is doing, you can try pulling up the CockroachDB Admin UI by port-forwarding from your local machine to one of the pods (replacing `my-release-cockroachdb-0` with the name of one of your pods: + +```shell +kubectl port-forward my-release-cockroachdb-0 8080 +``` + +You should then be able to access the Admin UI by visiting in your web browser. + +### Failover + +If any CockroachDB member fails, it is restarted or recreated automatically by the Kubernetes infrastructure, and will re-join the cluster automatically when it comes back up. You can test this scenario by killing any of the CockroachDB pods: + +```shell +kubectl delete pod my-release-cockroachdb-1 +``` + +```shell +kubectl get pods -l "app.kubernetes.io/instance=my-release,app.kubernetes.io/component=cockroachdb" +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 5m +my-release-cockroachdb-2 1/1 Running 0 5m +``` + +After a while: + +```shell +kubectl get pods -l "app.kubernetes.io/instance=my-release,app.kubernetes.io/component=cockroachdb" +``` + +``` +NAME READY STATUS RESTARTS AGE +my-release-cockroachdb-0 1/1 Running 0 5m +my-release-cockroachdb-1 1/1 Running 0 20s +my-release-cockroachdb-2 1/1 Running 0 5m +``` + +You can check the state of re-joining from the new pod's logs: + +```shell +kubectl logs my-release-cockroachdb-1 +``` + +``` +[...] +I161028 19:32:09.754026 1 server/node.go:586 [n1] node connected via gossip and +verified as part of cluster {"35ecbc27-3f67-4e7d-9b8f-27c31aae17d6"} +[...] +cockroachdb-0.my-release-cockroachdb.default.svc.cluster.local:26257 +build: beta-20161027-55-gd2d3c7f @ 2016/10/28 19:27:25 (go1.7.3) +admin: http://0.0.0.0:8080 +sql: +postgresql://root@my-release-cockroachdb-1.my-release-cockroachdb.default.svc.cluster.local:26257?sslmode=disable +logs: cockroach-data/logs +store[0]: path=cockroach-data +status: restarted pre-existing node +clusterID: {35ecbc27-3f67-4e7d-9b8f-27c31aae17d6} +nodeID: 2 +[...] +``` + +### NetworkPolicy + +To enable NetworkPolicy for CockroachDB, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin), and set `networkPolicy.enabled` to `yes`/`true`. + +For Kubernetes v1.5 & v1.6, you must also turn on NetworkPolicy by setting the `DefaultDeny` Namespace annotation. Note: this will enforce policy for _all_ pods in the Namespace: + +```shell +kubectl annotate namespace default "net.beta.kubernetes.io/network-policy={\"ingress\":{\"isolation\":\"DefaultDeny\"}}" +``` + +For more precise policy, set `networkPolicy.ingress.grpc` and `networkPolicy.ingress.http` rules. This will only allow pods that match the provided rules to connect to CockroachDB. + +### Scaling + +Scaling should be managed via the `helm upgrade` command. After resizing your cluster on your cloud environment (e.g., GKE or EKS), run the following command to add a pod. This assumes you scaled from 3 to 4 nodes: + +```shell +helm upgrade \ +my-release \ +cockroachdb/cockroachdb \ +--set statefulset.replicas=4 \ +--reuse-values +``` + +Note, that if you are running in secure mode (`tls.enabled` is `yes`/`true`) and increase the size of your cluster, you will also have to approve the CSR (certificate-signing request) of each new node (using `kubectl get csr` and `kubectl certificate approve`). + +[1]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity +[2]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity +[3]: https://cert-manager.io/ +[4]: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass +[5]: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/app-readme.md b/charts/cockroach-labs/cockroachdb/14.0.3/app-readme.md new file mode 100644 index 0000000000..8fcc1fd6fb --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/app-readme.md @@ -0,0 +1,9 @@ +# CockroachDB Chart + +CockroachDB is a Distributed SQL database that runs natively in Kubernetes. It gives you resilient, horizontal scale across multiple clouds with always-on availability and data partitioned by location. + +CockroachDB scales horizontally without reconfiguration or need for a massive architectural overhaul. Simply add a new node to the cluster and CockroachDB takes care of the underlying complexity. + + - Scale by simply adding new nodes to a CockroachDB cluster + - Automate balancing and distribution of ranges, not shards + - Optimize server utilization evenly across all nodes diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/NOTES.txt b/charts/cockroach-labs/cockroachdb/14.0.3/templates/NOTES.txt new file mode 100644 index 0000000000..13b421f624 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/NOTES.txt @@ -0,0 +1,50 @@ +CockroachDB can be accessed via port {{ .Values.service.ports.grpc.external.port }} at the +following DNS name from within your cluster: + +{{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }}.svc.cluster.local + +Because CockroachDB supports the PostgreSQL wire protocol, you can connect to +the cluster using any available PostgreSQL client. + +{{- if not .Values.tls.enabled }} + +For example, you can open up a SQL shell to the cluster by running: + + kubectl run -it --rm cockroach-client \ + --image=cockroachdb/cockroach \ + --restart=Never \ + {{- if .Values.networkPolicy.enabled }} + --labels="{{ template "cockroachdb.fullname" . }}-client=true" \ + {{- end }} + --command -- \ + ./cockroach sql --insecure --host={{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }} + +From there, you can interact with the SQL shell as you would any other SQL +shell, confident that any data you write will be safe and available even if +parts of your cluster fail. +{{- else }} + +Note that because the cluster is running in secure mode, any client application +that you attempt to connect will either need to have a valid client certificate +or a valid username and password. +{{- end }} + +{{- if and (.Values.networkPolicy.enabled) (not (empty .Values.networkPolicy.ingress.grpc)) }} + +Note: Since NetworkPolicy is enabled, the only Pods allowed to connect to this +CockroachDB cluster are: + +1. Having the label: "{{ template "cockroachdb.fullname" . }}-client=true" + +2. Matching the following rules: {{- toYaml .Values.networkPolicy.ingress.grpc | nindent 0 }} +{{- end }} + +Finally, to open up the CockroachDB admin UI, you can port-forward from your +local machine into one of the instances in the cluster: + + kubectl port-forward -n {{ .Release.Namespace }} {{ template "cockroachdb.fullname" . }}-0 {{ index .Values.conf `http-port` | int64 }} + +Then you can access the admin UI at http{{ if .Values.tls.enabled }}s{{ end }}://localhost:{{ index .Values.conf `http-port` | int64 }}/ in your web browser. + +For more information on using CockroachDB, please see the project's docs at: +https://www.cockroachlabs.com/docs/ diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/_helpers.tpl b/charts/cockroach-labs/cockroachdb/14.0.3/templates/_helpers.tpl new file mode 100644 index 0000000000..9ef769a70a --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/_helpers.tpl @@ -0,0 +1,291 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "cockroachdb.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cockroachdb.fullname" -}} +{{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 56 | trimSuffix "-" -}} +{{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 56 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 56 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name for cluster scope resource. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name with release namespace appended at the end. +*/}} +{{- define "cockroachdb.clusterfullname" -}} +{{- if .Values.fullnameOverride -}} + {{- printf "%s-%s" .Values.fullnameOverride .Release.Namespace | trunc 56 | trimSuffix "-" -}} +{{- else -}} + {{- $name := default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- printf "%s-%s" .Release.Name .Release.Namespace | trunc 56 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s-%s" .Release.Name $name .Release.Namespace | trunc 56 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cockroachdb.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create the name of the ServiceAccount to use. +*/}} +{{- define "cockroachdb.serviceAccount.name" -}} +{{- if .Values.statefulset.serviceAccount.create -}} + {{- default (include "cockroachdb.fullname" .) .Values.statefulset.serviceAccount.name -}} +{{- else -}} + {{- default "default" .Values.statefulset.serviceAccount.name -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for NetworkPolicy. +*/}} +{{- define "cockroachdb.networkPolicy.apiVersion" -}} +{{- if semverCompare ">=1.4-0, <=1.7-0" .Capabilities.KubeVersion.Version -}} + {{- print "extensions/v1beta1" -}} +{{- else if semverCompare "^1.7-0" .Capabilities.KubeVersion.Version -}} + {{- print "networking.k8s.io/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return the appropriate apiVersion for StatefulSets +*/}} +{{- define "cockroachdb.statefulset.apiVersion" -}} +{{- if semverCompare "<1.12-0" .Capabilities.KubeVersion.Version -}} + {{- print "apps/v1beta1" -}} +{{- else -}} + {{- print "apps/v1" -}} +{{- end -}} +{{- end -}} + +{{/* +Return CockroachDB store expression +*/}} +{{- define "cockroachdb.conf.store" -}} +{{- $isInMemory := eq (.Values.conf.store.type | toString) "mem" -}} +{{- $persistentSize := empty .Values.conf.store.size | ternary .Values.storage.persistentVolume.size .Values.conf.store.size -}} + +{{- $store := dict -}} +{{- $_ := set $store "type" ($isInMemory | ternary "type=mem" "") -}} +{{- $_ := set $store "path" ($isInMemory | ternary "" (print "path=" .Values.conf.path)) -}} +{{- $_ := set $store "size" (print "size=" ($isInMemory | ternary .Values.conf.store.size $persistentSize)) -}} +{{- $_ := set $store "attrs" (empty .Values.conf.store.attrs | ternary "" (print "attrs=" .Values.conf.store.attrs)) -}} + +{{ compact (values $store) | join "," }} +{{- end -}} + +{{/* +Define the default values for the certificate selfSigner inputs +*/}} +{{- define "selfcerts.fullname" -}} + {{- printf "%s-%s" (include "cockroachdb.fullname" .) "self-signer" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "rotatecerts.fullname" -}} + {{- printf "%s-%s" (include "cockroachdb.fullname" .) "rotate-self-signer" | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "selfcerts.minimumCertDuration" -}} + {{- if .Values.tls.certs.selfSigner.minimumCertDuration -}} + {{- print (.Values.tls.certs.selfSigner.minimumCertDuration | trimSuffix "h") -}} + {{- else }} + {{- $minCertDuration := min (sub (.Values.tls.certs.selfSigner.clientCertDuration | trimSuffix "h" ) (.Values.tls.certs.selfSigner.clientCertExpiryWindow | trimSuffix "h")) (sub (.Values.tls.certs.selfSigner.nodeCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.nodeCertExpiryWindow | trimSuffix "h")) -}} + {{- print $minCertDuration -}} + {{- end }} +{{- end -}} + +{{/* +Define the cron schedules for certificate rotate jobs and converting from hours to valid cron string. +We assume that each month has 31 days, hence the cron job may run few days earlier in a year. In a cron schedule, +we can not set a cron of more than a year, hence we try to run the cron in such a way that the cron run comes to +as close possible to the expiry window. However, it is possible that cron may run earlier than the expiry window. +*/}} +{{- define "selfcerts.caRotateSchedule" -}} +{{- $tempHours := sub (.Values.tls.certs.selfSigner.caCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h") -}} +{{- $days := "*" -}} +{{- $months := "*" -}} +{{- $hours := mod $tempHours 24 -}} +{{- if not (eq $hours $tempHours) -}} +{{- $tempDays := div $tempHours 24 -}} +{{- $days = mod $tempDays 31 -}} +{{- if not (eq $days $tempDays) -}} +{{- $days = add $days 1 -}} +{{- $tempMonths := div $tempDays 31 -}} +{{- $months = mod $tempMonths 12 -}} +{{- if not (eq $months $tempMonths) -}} +{{- $months = add $months 1 -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if ne (toString $months) "*" -}} +{{- $months = printf "*/%s" (toString $months) -}} +{{- else -}} +{{- if ne (toString $days) "*" -}} +{{- $days = printf "*/%s" (toString $days) -}} +{{- else -}} +{{- if ne $hours 0 -}} +{{- $hours = printf "*/%s" (toString $hours) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- printf "0 %s %s %s *" (toString $hours) (toString $days) (toString $months) -}} +{{- end -}} + +{{- define "selfcerts.clientRotateSchedule" -}} +{{- $tempHours := int64 (include "selfcerts.minimumCertDuration" .) -}} +{{- $days := "*" -}} +{{- $months := "*" -}} +{{- $hours := mod $tempHours 24 -}} +{{- if not (eq $hours $tempHours) -}} +{{- $tempDays := div $tempHours 24 -}} +{{- $days = mod $tempDays 31 -}} +{{- if not (eq $days $tempDays) -}} +{{- $days = add $days 1 -}} +{{- $tempMonths := div $tempDays 31 -}} +{{- $months = mod $tempMonths 12 -}} +{{- if not (eq $months $tempMonths) -}} +{{- $months = add $months 1 -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if ne (toString $months) "*" -}} +{{- $months = printf "*/%s" (toString $months) -}} +{{- else -}} +{{- if ne (toString $days) "*" -}} +{{- $days = printf "*/%s" (toString $days) -}} +{{- else -}} +{{- if ne $hours 0 -}} +{{- $hours = printf "*/%s" (toString $hours) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- printf "0 %s %s %s *" (toString $hours) (toString $days) (toString $months) -}} +{{- end -}} + +{{/* +Define the appropriate validations for the certificate selfSigner inputs +*/}} + +{{/* +Validate that if caProvided is true, then the caSecret must not be empty and secret must be present in the namespace. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.caProvidedValidation" -}} +{{- if .Values.tls.certs.selfSigner.caProvided -}} +{{- if eq "" .Values.tls.certs.selfSigner.caSecret -}} + {{ fail "CA secret can't be empty if caProvided is set to true" }} +{{- else -}} + {{- if not (lookup "v1" "Secret" .Release.Namespace .Values.tls.certs.selfSigner.caSecret) }} + {{ fail "CA secret is not present in the release namespace" }} + {{- end }} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Validate that if caCertDuration or caCertExpiryWindow must not be empty and caCertExpiryWindow must be greater than +minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.caCertValidation" -}} +{{- if not .Values.tls.certs.selfSigner.caProvided -}} +{{- if or (not .Values.tls.certs.selfSigner.caCertDuration) (not .Values.tls.certs.selfSigner.caCertExpiryWindow) }} + {{ fail "CA cert duration or CA cert expiry window can not be empty" }} +{{- else }} +{{- if gt (int64 (include "selfcerts.minimumCertDuration" .)) (int64 (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h")) -}} + {{ fail "CA cert expiration window should not be less than minimum Cert duration" }} +{{- end -}} +{{- if gt (int64 (include "selfcerts.minimumCertDuration" .)) (sub (.Values.tls.certs.selfSigner.caCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.caCertExpiryWindow | trimSuffix "h")) -}} + {{ fail "CA cert Duration minus CA cert expiration window should not be less than minimum Cert duration" }} +{{- end -}} +{{- end -}} +{{- end }} +{{- end -}} + +{{/* +Validate that if clientCertDuration must not be empty and it must be greater than minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.clientCertValidation" -}} +{{- if or (not .Values.tls.certs.selfSigner.clientCertDuration) (not .Values.tls.certs.selfSigner.clientCertExpiryWindow) }} + {{ fail "Client cert duration can not be empty" }} +{{- else }} +{{- if lt (sub (.Values.tls.certs.selfSigner.clientCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.clientCertExpiryWindow | trimSuffix "h")) (int64 (include "selfcerts.minimumCertDuration" .)) }} + {{ fail "Client cert duration minus client cert expiry window should not be less than minimum Cert duration" }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Validate that nodeCertDuration must not be empty and nodeCertDuration minus nodeCertExpiryWindow must be greater than minimumCertDuration. +*/}} +{{- define "cockroachdb.tls.certs.selfSigner.nodeCertValidation" -}} +{{- if or (not .Values.tls.certs.selfSigner.nodeCertDuration) (not .Values.tls.certs.selfSigner.nodeCertExpiryWindow) }} + {{ fail "Node cert duration can not be empty" }} +{{- else }} +{{- if lt (sub (.Values.tls.certs.selfSigner.nodeCertDuration | trimSuffix "h") (.Values.tls.certs.selfSigner.nodeCertExpiryWindow | trimSuffix "h")) (int64 (include "selfcerts.minimumCertDuration" .))}} + {{ fail "Node cert duration minus node cert expiry window should not be less than minimum Cert duration" }} +{{- end }} +{{- end }} +{{- end -}} + +{{/* +Validate that if user enabled tls, then either self-signed certificates or certificate manager is enabled +*/}} +{{- define "cockroachdb.tlsValidation" -}} +{{- if .Values.tls.enabled -}} +{{- if and .Values.tls.certs.selfSigner.enabled .Values.tls.certs.certManager -}} + {{ fail "Can not enable the self signed certificates and certificate manager at the same time" }} +{{- end -}} +{{- if and (not .Values.tls.certs.selfSigner.enabled) (not .Values.tls.certs.certManager) -}} + {{- if not .Values.tls.certs.provided -}} + {{ fail "You have to enable either self signed certificates or certificate manager, if you have enabled tls" }} + {{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} + + +{{- define "cockroachdb.tls.certs.selfSigner.validation" -}} +{{ include "cockroachdb.tls.certs.selfSigner.caProvidedValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.caCertValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.clientCertValidation" . }} +{{ include "cockroachdb.tls.certs.selfSigner.nodeCertValidation" . }} +{{- end -}} + +{{- define "cockroachdb.securityContext.versionValidation" }} +{{- /* Allow using `securityContext` for custom images. */}} +{{- if ne "cockroachdb/cockroach" .Values.image.repository -}} + {{ print true }} +{{- else -}} +{{- if semverCompare ">=22.1.2" .Values.image.tag -}} + {{ print true }} +{{- else -}} +{{- if semverCompare ">=21.2.13, <22.1.0" .Values.image.tag -}} + {{ print true }} +{{- else -}} + {{ print false }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/backendconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/backendconfig.yaml new file mode 100644 index 0000000000..2edc88619a --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/backendconfig.yaml @@ -0,0 +1,21 @@ +{{- if .Values.iap.enabled }} +apiVersion: cloud.google.com/v1beta1 +kind: BackendConfig +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + iap: + enabled: true + oauthclientCredentials: + secretName: {{ template "cockroachdb.fullname" . }}.iap + timeoutSec: 120 +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.ca.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.ca.yaml new file mode 100644 index 0000000000..4043fafb0f --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.ca.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-ca-cert + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.caCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.caCertExpiryWindow }} + isCA: true + secretName: {{ .Values.tls.certs.caSecret }} + privateKey: + algorithm: ECDSA + size: 256 + commonName: root + subject: + organizations: + - Cockroach + issuerRef: + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.client.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.client.yaml new file mode 100644 index 0000000000..dd0272f3e2 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.client.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-root-client + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.clientCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.clientCertExpiryWindow }} + usages: + - digital signature + - key encipherment + - client auth + privateKey: + algorithm: RSA + size: 2048 + commonName: root + subject: + organizations: + - Cockroach + secretName: {{ .Values.tls.certs.clientRootSecret }} + issuerRef: + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + kind: Issuer + group: cert-manager.io + {{- else }} + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.issuer.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.issuer.yaml new file mode 100644 index 0000000000..5cf579ff9d --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.issuer.yaml @@ -0,0 +1,20 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ca: + secretName: {{ .Values.tls.certs.caSecret }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.node.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.node.yaml new file mode 100644 index 0000000000..05e909d0b0 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/certificate.node.yaml @@ -0,0 +1,50 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.certManager }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ template "cockroachdb.fullname" . }}-node + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + duration: {{ .Values.tls.certs.certManagerIssuer.nodeCertDuration }} + renewBefore: {{ .Values.tls.certs.certManagerIssuer.nodeCertExpiryWindow }} + usages: + - digital signature + - key encipherment + - server auth + - client auth + privateKey: + algorithm: RSA + size: 2048 + commonName: node + subject: + organizations: + - Cockroach + dnsNames: + - "localhost" + - "127.0.0.1" + - {{ printf "%s-public" (include "cockroachdb.fullname" .) | quote }} + - {{ printf "%s-public.%s" (include "cockroachdb.fullname" .) .Release.Namespace | quote }} + - {{ printf "%s-public.%s.svc.%s" (include "cockroachdb.fullname" .) .Release.Namespace .Values.clusterDomain | quote }} + - {{ printf "*.%s" (include "cockroachdb.fullname" .) | quote }} + - {{ printf "*.%s.%s" (include "cockroachdb.fullname" .) .Release.Namespace | quote }} + - {{ printf "*.%s.%s.svc.%s" (include "cockroachdb.fullname" .) .Release.Namespace .Values.clusterDomain | quote }} + secretName: {{ .Values.tls.certs.nodeSecret }} + issuerRef: + {{- if .Values.tls.certs.certManagerIssuer.isSelfSignedIssuer }} + name: {{ template "cockroachdb.fullname" . }}-ca-issuer + kind: Issuer + group: cert-manager.io + {{- else }} + name: {{ .Values.tls.certs.certManagerIssuer.name }} + kind: {{ .Values.tls.certs.certManagerIssuer.kind }} + group: {{ .Values.tls.certs.certManagerIssuer.group }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrole.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrole.yaml new file mode 100644 index 0000000000..6b8a3dc5f7 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrole.yaml @@ -0,0 +1,19 @@ +{{- if and .Values.tls.enabled (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.clusterfullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: ["certificates.k8s.io"] + resources: ["certificatesigningrequests"] + verbs: ["create", "get", "watch"] +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrolebinding.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrolebinding.yaml new file mode 100644 index 0000000000..3c18694efd --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/clusterrolebinding.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.tls.enabled (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.clusterfullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "cockroachdb.clusterfullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-ca-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-ca-certSelfSigner.yaml new file mode 100644 index 0000000000..4cd53900cb --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-ca-certSelfSigner.yaml @@ -0,0 +1,62 @@ +{{- if and .Values.tls.enabled (and .Values.tls.certs.selfSigner.enabled (not .Values.tls.certs.selfSigner.caProvided)) }} + {{- if .Values.tls.certs.selfSigner.rotateCerts }} + {{- if .Capabilities.APIVersions.Has "batch/v1/CronJob" }} +apiVersion: batch/v1 + {{- else }} +apiVersion: batch/v1beta1 + {{- end }} +kind: CronJob +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + schedule: {{ template "selfcerts.caRotateSchedule" . }} + jobTemplate: + spec: + backoffLimit: 1 + template: + metadata: + {{- with .Values.tls.selfSigner.labels }} + labels: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.annotations }} + annotations: {{- toYaml . | nindent 12 }} + {{- end }} + spec: + restartPolicy: Never + {{- with .Values.tls.selfSigner.affinity }} + affinity: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.tolerations }} + tolerations: {{- toYaml . | nindent 12 }} + {{- end }} + containers: + - name: cert-rotate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - rotate + - --ca + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + - --ca-cron={{ template "selfcerts.caRotateSchedule" . }} + - --readiness-wait={{ .Values.tls.certs.selfSigner.readinessWait }} + - --pod-update-timeout={{ .Values.tls.certs.selfSigner.podUpdateTimeout }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + serviceAccountName: {{ template "rotatecerts.fullname" . }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-client-node-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-client-node-certSelfSigner.yaml new file mode 100644 index 0000000000..d500cbeb6c --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/cronjob-client-node-certSelfSigner.yaml @@ -0,0 +1,69 @@ +{{- if and .Values.tls.certs.selfSigner.enabled .Values.tls.certs.selfSigner.rotateCerts }} + {{- if .Capabilities.APIVersions.Has "batch/v1/CronJob" }} +apiVersion: batch/v1 + {{- else }} +apiVersion: batch/v1beta1 + {{- end }} +kind: CronJob +metadata: + name: {{ template "rotatecerts.fullname" . }}-client + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + schedule: {{ template "selfcerts.clientRotateSchedule" . }} + jobTemplate: + spec: + backoffLimit: 1 + template: + metadata: + {{- with .Values.tls.selfSigner.labels }} + labels: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.annotations }} + annotations: {{- toYaml . | nindent 12 }} + {{- end }} + spec: + restartPolicy: Never + {{- with .Values.tls.selfSigner.affinity }} + affinity: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.tls.selfSigner.tolerations }} + tolerations: {{- toYaml . | nindent 12 }} + {{- end }} + containers: + - name: cert-rotate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - rotate + {{- if .Values.tls.certs.selfSigner.caProvided }} + - --ca-secret={{ .Values.tls.certs.selfSigner.caSecret }} + {{- else }} + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + {{- end }} + - --client + - --client-duration={{ .Values.tls.certs.selfSigner.clientCertDuration }} + - --client-expiry={{ .Values.tls.certs.selfSigner.clientCertExpiryWindow }} + - --node + - --node-duration={{ .Values.tls.certs.selfSigner.nodeCertDuration }} + - --node-expiry={{ .Values.tls.certs.selfSigner.nodeCertExpiryWindow }} + - --node-client-cron={{ template "selfcerts.clientRotateSchedule" . }} + - --readiness-wait={{ .Values.tls.certs.selfSigner.readinessWait }} + - --pod-update-timeout={{ .Values.tls.certs.selfSigner.podUpdateTimeout }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + serviceAccountName: {{ template "rotatecerts.fullname" . }} + {{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/ingress.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/ingress.yaml new file mode 100644 index 0000000000..2fa6373c87 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/ingress.yaml @@ -0,0 +1,90 @@ +{{- if .Values.ingress.enabled -}} +{{- $paths := .Values.ingress.paths -}} +{{- $ports := .Values.service.ports -}} +{{- $fullName := include "cockroachdb.fullname" . -}} +{{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} +apiVersion: networking.k8s.io/v1 +{{- else if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress" }} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: +{{- if or .Values.ingress.annotations .Values.iap.enabled }} + annotations: + {{- range $key, $value := .Values.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- if .Values.iap.enabled }} + kubernetes.io/ingress.class: "gce" + kubernetes.io/ingress.allow-http: "false" + {{- end }} +{{- end }} + name: {{ $fullName }}-ingress + namespace: {{ .Release.Namespace }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ $.Release.Name | quote }} + app.kubernetes.io/managed-by: {{ $.Release.Service | quote }} +{{- if .Values.ingress.labels }} +{{- toYaml .Values.ingress.labels | nindent 4 }} +{{- end }} +spec: + rules: + {{- if .Values.ingress.hosts }} + {{- range $host := .Values.ingress.hosts }} + - host: {{ $host }} + http: + paths: + {{- range $path := $paths }} + - path: {{ $path | quote }} + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + {{- if $.Values.iap.enabled }} + pathType: ImplementationSpecific + {{- else }} + pathType: Prefix + {{- end }} + {{- end }} + backend: + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + service: + name: {{ $fullName }}-public + port: + name: {{ $ports.http.name | quote }} + {{- else }} + serviceName: {{ $fullName }}-public + servicePort: {{ $ports.http.name | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- else }} + - http: + paths: + {{- range $path := $paths }} + - path: {{ $path | quote }} + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + {{- if $.Values.iap.enabled }} + pathType: ImplementationSpecific + {{- else }} + pathType: Prefix + {{- end }} + {{- end }} + backend: + {{- if $.Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" }} + service: + name: {{ $fullName }}-public + port: + name: {{ $ports.http.name | quote }} + {{- else }} + serviceName: {{ $fullName }}-public + servicePort: {{ $ports.http.name | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: +{{- toYaml .Values.ingress.tls | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-certSelfSigner.yaml new file mode 100644 index 0000000000..54ed2cad3e --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-certSelfSigner.yaml @@ -0,0 +1,83 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "4" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + template: + metadata: + name: {{ template "selfcerts.fullname" . }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.tls.selfSigner.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + restartPolicy: Never + {{- with .Values.tls.selfSigner.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cert-generate-job + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - generate + {{- if .Values.tls.certs.selfSigner.caProvided }} + - --ca-secret={{ .Values.tls.certs.selfSigner.caSecret }} + {{- else }} + - --ca-duration={{ .Values.tls.certs.selfSigner.caCertDuration }} + - --ca-expiry={{ .Values.tls.certs.selfSigner.caCertExpiryWindow }} + {{- end }} + - --client-duration={{ .Values.tls.certs.selfSigner.clientCertDuration }} + - --client-expiry={{ .Values.tls.certs.selfSigner.clientCertExpiryWindow }} + - --node-duration={{ .Values.tls.certs.selfSigner.nodeCertDuration }} + - --node-expiry={{ .Values.tls.certs.selfSigner.nodeCertExpiryWindow }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: NAMESPACE + value: {{ .Release.Namespace | quote }} + - name: CLUSTER_DOMAIN + value: {{ .Values.clusterDomain}} + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + serviceAccountName: {{ template "selfcerts.fullname" . }} +{{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-cleaner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-cleaner.yaml new file mode 100644 index 0000000000..1503ac4594 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job-cleaner.yaml @@ -0,0 +1,70 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "selfcerts.fullname" . }}-cleaner + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-delete + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} +spec: + backoffLimit: 1 + template: + metadata: + name: {{ template "selfcerts.fullname" . }}-cleaner + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.tls.selfSigner.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + restartPolicy: Never + {{- with .Values.tls.selfSigner.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tls.selfSigner.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cleaner + image: "{{ .Values.tls.selfSigner.image.registry }}/{{ .Values.tls.selfSigner.image.repository }}:{{ .Values.tls.selfSigner.image.tag }}" + imagePullPolicy: "{{ .Values.tls.selfSigner.image.pullPolicy }}" + args: + - cleanup + - --namespace={{ .Release.Namespace }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + {{- if and .Values.tls.certs.selfSigner.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + serviceAccountName: {{ template "rotatecerts.fullname" . }} +{{- end}} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/job.init.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job.init.yaml new file mode 100644 index 0000000000..dbc1eaa176 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/job.init.yaml @@ -0,0 +1,303 @@ +{{ $isClusterInitEnabled := and (eq (len .Values.conf.join) 0) (not (index .Values.conf `single-node`)) }} +{{ $isDatabaseProvisioningEnabled := .Values.init.provisioning.enabled }} +{{- if or $isClusterInitEnabled $isDatabaseProvisioningEnabled }} + {{ template "cockroachdb.tlsValidation" . }} +kind: Job +apiVersion: batch/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-init + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation + {{- with .Values.init.jobAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if and .Values.init.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + runAsGroup: 1000 + runAsUser: 1000 + fsGroup: 1000 + runAsNonRoot: true + {{- end }} + {{- end }} + restartPolicy: OnFailure + terminationGracePeriodSeconds: {{ .Values.init.terminationGracePeriodSeconds }} + {{- if or .Values.image.credentials (and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager)) }} + imagePullSecrets: + {{- if .Values.image.credentials }} + - name: {{ template "cockroachdb.fullname" . }}.db.registry + {{- end }} + {{- if and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} + - name: {{ template "cockroachdb.fullname" . }}.self-signed-certs.registry + {{- end }} + {{- end }} + serviceAccountName: {{ template "cockroachdb.serviceAccount.name" . }} + {{- if .Values.tls.enabled }} + initContainers: + - name: copy-certs + image: {{ .Values.tls.copyCerts.image | quote }} + imagePullPolicy: {{ .Values.tls.selfSigner.image.pullPolicy | quote }} + command: + - /bin/sh + - -c + - "cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if and .Values.init.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs/ + - name: certs-secret + mountPath: /certs/ + {{- with .Values.tls.copyCerts.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- with .Values.init.affinity }} + affinity: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.init.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: cluster-init + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + # Run the command in an `while true` loop because this Job is bound + # to come up before the CockroachDB Pods (due to the time needed to + # get PersistentVolumes attached to Nodes), and sleeping 5 seconds + # between attempts is much better than letting the Pod fail when + # the init command does and waiting out Kubernetes' non-configurable + # exponential back-off for Pod restarts. + # Command completes either when cluster initialization succeeds, + # or when cluster has been initialized already. + command: + - /bin/bash + - -c + - >- + {{- if $isClusterInitEnabled }} + initCluster() { + while true; do + local output=$( + set -x; + + /cockroach/cockroach init \ + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach-certs/ \ + {{- else }} + --insecure \ + {{- end }} + {{- with index .Values.conf "cluster-name" }} + --cluster-name={{.}} \ + {{- end }} + --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} + :{{ .Values.service.ports.grpc.internal.port | int64 }} \ + {{- if .Values.init.pcr.enabled -}} + {{- if .Values.init.pcr.isPrimary }} + --virtualized \ + {{- else }} + --virtualized-empty \ + {{- end }} + {{- end }} + 2>&1); + + local exitCode="$?"; + echo $output; + + if [[ "$output" =~ .*"Cluster successfully initialized".* || "$output" =~ .*"cluster has already been initialized".* ]]; then + break; + fi + + echo "Cluster is not ready to be initialized, retrying in 5 seconds" + sleep 5; + done + } + + initCluster; + {{- end }} + + {{- if $isDatabaseProvisioningEnabled }} + provisionCluster() { + while true; do + /cockroach/cockroach sql \ + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach-certs/ \ + {{- else }} + --insecure \ + {{- end }} + --host={{ template "cockroachdb.fullname" . }}-0.{{ template "cockroachdb.fullname" . -}} + :{{ .Values.service.ports.grpc.internal.port | int64 }} \ + --execute=" + {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + SET CLUSTER SETTING {{ $clusterSetting }} = '${{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING'; + {{- end }} + + {{- range $user := .Values.init.provisioning.users }} + CREATE USER IF NOT EXISTS {{ $user.name }} WITH + {{- if $user.password }} + PASSWORD '${{ $user.name }}_PASSWORD' + {{- else }} + PASSWORD null + {{- end }} + {{ join " " $user.options }} + ; + {{- end }} + + {{- range $database := .Values.init.provisioning.databases }} + CREATE DATABASE IF NOT EXISTS {{ $database.name }} + {{- if $database.options }} + {{ join " " $database.options }} + {{- end }} + ; + + {{- range $owner := $database.owners }} + GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }}; + {{- end }} + + {{- range $owner := $database.owners_with_grant_option }} + GRANT ALL ON DATABASE {{ $database.name }} TO {{ $owner }} WITH GRANT OPTION; + {{- end }} + + {{- if $database.backup }} + CREATE SCHEDULE IF NOT EXISTS {{ $database.name }}_scheduled_backup + FOR BACKUP DATABASE {{ $database.name }} INTO '{{ $database.backup.into }}' + + {{- if $database.backup.options }} + WITH {{ join "," $database.backup.options }} + {{- end }} + RECURRING '{{ $database.backup.recurring }}' + {{- if $database.backup.fullBackup }} + FULL BACKUP '{{ $database.backup.fullBackup }}' + {{- else }} + FULL BACKUP ALWAYS + {{- end }} + + {{- if and $database.backup.schedule $database.backup.schedule.options }} + WITH SCHEDULE OPTIONS {{ join "," $database.backup.schedule.options }} + {{- end }} + ; + {{- end }} + {{- end }} + " + &>/dev/null; + + local exitCode="$?"; + + if [[ "$exitCode" -eq "0" ]] + then break; + fi + + sleep 5; + done + + echo "Provisioning completed successfully"; + } + + provisionCluster; + {{- end }} + env: + {{- $secretName := printf "%s-init" (include "cockroachdb.fullname" .) }} + {{- range $user := .Values.init.provisioning.users }} + {{- if $user.password }} + - name: {{ $user.name }}_PASSWORD + valueFrom: + secretKeyRef: + name: {{ $secretName }} + key: {{ $user.name }}-password + {{- end }} + {{- end }} + {{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + {{- if $clusterSettingValue }} + - name: {{ $clusterSetting | replace "." "_" }}_CLUSTER_SETTING + valueFrom: + secretKeyRef: + name: {{ $secretName }} + key: {{ $clusterSetting | replace "." "-" }}-cluster-setting + {{- end }} + {{- end }} + {{- if .Values.tls.enabled }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs/ + {{- end }} + {{- with .Values.init.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- if and .Values.init.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + {{- end }} + {{- if .Values.tls.enabled }} + volumes: + - name: client-certs + emptyDir: {} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + - name: certs-secret + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + projected: + sources: + - secret: + {{- if .Values.tls.certs.selfSigner.enabled }} + name: {{ template "cockroachdb.fullname" . }}-client-secret + {{ else }} + name: {{ .Values.tls.certs.clientRootSecret }} + {{ end -}} + items: + - key: ca.crt + path: ca.crt + mode: 0400 + - key: tls.crt + path: client.root.crt + mode: 0400 + - key: tls.key + path: client.root.key + mode: 0400 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.clientRootSecret }} + defaultMode: 0400 + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/networkpolicy.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/networkpolicy.yaml new file mode 100644 index 0000000000..d41afa32ba --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/networkpolicy.yaml @@ -0,0 +1,59 @@ +{{- if .Values.networkPolicy.enabled }} +kind: NetworkPolicy +apiVersion: {{ template "cockroachdb.networkPolicy.apiVersion" . }} +metadata: + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + ingress: + - ports: + - port: grpc + {{- with .Values.networkPolicy.ingress.grpc }} + from: + # Allow connections via custom rules. + {{- toYaml . | nindent 8 }} + # Allow client connection via pre-considered label. + - podSelector: + matchLabels: + {{ template "cockroachdb.fullname" . }}-client: "true" + # Allow other CockroachDBs to connect to form a cluster. + - podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 14 }} + {{- end }} + {{- if gt (.Values.statefulset.replicas | int64) 1 }} + # Allow init Job to connect to bootstrap a cluster. + - podSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.init.labels }} + {{- toYaml . | nindent 14 }} + {{- end }} + {{- end }} + {{- end }} + # Allow connections to admin UI and for Prometheus. + - ports: + - port: http + {{- with .Values.networkPolicy.ingress.http }} + from: {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/poddisruptionbudget.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/poddisruptionbudget.yaml new file mode 100644 index 0000000000..f707e40541 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/poddisruptionbudget.yaml @@ -0,0 +1,26 @@ +kind: PodDisruptionBudget +{{- if or (.Capabilities.APIVersions.Has "policy/v1") (semverCompare ">=1.21-0" .Capabilities.KubeVersion.Version) }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +metadata: + name: {{ template "cockroachdb.fullname" . }}-budget + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + maxUnavailable: {{ .Values.statefulset.budget.maxUnavailable | int64 }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certRotateSelfSigner.yaml new file mode 100644 index 0000000000..f0e2b90cea --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certRotateSelfSigner.yaml @@ -0,0 +1,27 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "update", "delete"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get"] + resourceNames: + - {{ template "cockroachdb.fullname" . }} + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get"] +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certSelfSigner.yaml new file mode 100644 index 0000000000..1cbaab3dd3 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role-certSelfSigner.yaml @@ -0,0 +1,33 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "2" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "update", "delete"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get"] + resourceNames: + - {{ template "cockroachdb.fullname" . }} + - apiGroups: [""] + resources: ["pods"] + verbs: ["delete", "get"] +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/role.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role.yaml new file mode 100644 index 0000000000..ebe5ce8ae7 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/role.yaml @@ -0,0 +1,23 @@ +{{- if .Values.tls.enabled }} +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +rules: + - apiGroups: [""] + resources: ["secrets"] + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + verbs: ["get"] + {{- else }} + verbs: ["create", "get"] + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certRotateSelfSigner.yaml new file mode 100644 index 0000000000..c1a45f7977 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certRotateSelfSigner.yaml @@ -0,0 +1,23 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "rotatecerts.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certSelfSigner.yaml new file mode 100644 index 0000000000..5725d02a41 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding-certSelfSigner.yaml @@ -0,0 +1,29 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "3" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "selfcerts.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding.yaml new file mode 100644 index 0000000000..00d9f9a551 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/rolebinding.yaml @@ -0,0 +1,23 @@ +{{- if .Values.tls.enabled }} +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "cockroachdb.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.backendconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.backendconfig.yaml new file mode 100644 index 0000000000..61103060a6 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.backendconfig.yaml @@ -0,0 +1,25 @@ +{{- if .Values.iap.enabled }} +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}.iap + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if eq "" .Values.iap.clientId }} + {{ fail "iap.clientID can't be empty if iap.enabled is set to true" }} + {{- end }} + client_id: {{ .Values.iap.clientId | b64enc }} + {{- if eq "" .Values.iap.clientSecret }} + {{ fail "iap.clientSecret can't be empty if iap.enabled is set to true" }} + {{- end }} + client_secret: {{ .Values.iap.clientSecret | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.logconfig.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.logconfig.yaml new file mode 100644 index 0000000000..40b929ae75 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.logconfig.yaml @@ -0,0 +1,19 @@ +{{- if .Values.conf.log.enabled }} +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-log-config + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +stringData: + log-config.yaml: | + {{- toYaml .Values.conf.log.config | nindent 4 }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.registry.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.registry.yaml new file mode 100644 index 0000000000..a054069fbc --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secret.registry.yaml @@ -0,0 +1,23 @@ +{{- range $name, $cred := dict "db" (.Values.image.credentials) "init-certs" (.Values.tls.selfSigner.image.credentials) }} +{{- if not (empty $cred) }} +{{- if or (and (eq $name "init-certs") $.Values.tls.enabled) (ne $name "init-certs") }} +--- +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" $ }}.{{ $name }}.registry + namespace: {{ $.Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" $ }} + app.kubernetes.io/name: {{ template "cockroachdb.name" $ }} + app.kubernetes.io/instance: {{ $.Release.Name | quote }} + app.kubernetes.io/managed-by: {{ $.Release.Service | quote }} + {{- with $.Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +type: kubernetes.io/dockerconfigjson +data: + .dockerconfigjson: {{ printf `{"auths":{%s:{"auth":"%s"}}}` ($cred.registry | quote) (printf "%s:%s" $cred.username $cred.password | b64enc) | b64enc | quote }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/secrets.init.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secrets.init.yaml new file mode 100644 index 0000000000..4d13a35ffa --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/secrets.init.yaml @@ -0,0 +1,20 @@ +{{- if .Values.init.provisioning.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "cockroachdb.fullname" . }}-init + namespace: {{ .Release.Namespace | quote }} +type: Opaque +stringData: + +{{- range $user := .Values.init.provisioning.users }} +{{- if $user.password }} + {{ $user.name }}-password: {{ $user.password | quote }} +{{- end }} +{{- end }} + +{{- range $clusterSetting, $clusterSettingValue := .Values.init.provisioning.clusterSettings }} + {{ $clusterSetting | replace "." "-" }}-cluster-setting: {{ $clusterSettingValue | quote }} +{{- end }} + +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.discovery.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.discovery.yaml new file mode 100644 index 0000000000..8fe2a427ad --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.discovery.yaml @@ -0,0 +1,64 @@ +# This service only exists to create DNS entries for each pod in +# the StatefulSet such that they can resolve each other's IP addresses. +# It does not create a load-balanced ClusterIP and should not be used directly +# by clients in most circumstances. +kind: Service +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.service.discovery.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + # Use this annotation in addition to the actual field below because the + # annotation will stop being respected soon, but the field is broken in + # some versions of Kubernetes: + # https://github.com/kubernetes/kubernetes/issues/58662 + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" + # Enable automatic monitoring of all instances when Prometheus is running + # in the cluster. + {{- if .Values.prometheus.enabled }} + prometheus.io/scrape: "true" + prometheus.io/path: _status/vars + prometheus.io/port: {{ .Values.service.ports.http.port | quote }} + {{- end }} + {{- with .Values.service.discovery.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + clusterIP: None + # We want all Pods in the StatefulSet to have their addresses published for + # the sake of the other CockroachDB Pods even before they're ready, since they + # have to be able to talk to each other in order to become ready. + publishNotReadyAddresses: true + ports: + {{- $ports := .Values.service.ports }} + # The main port, served by gRPC, serves Postgres-flavor SQL, inter-node + # traffic and the CLI. + - name: {{ $ports.grpc.external.name | quote }} + port: {{ $ports.grpc.external.port | int64 }} + targetPort: grpc + {{- if ne ($ports.grpc.internal.port | int64) ($ports.grpc.external.port | int64) }} + - name: {{ $ports.grpc.internal.name | quote }} + port: {{ $ports.grpc.internal.port | int64 }} + targetPort: grpc + {{- end }} + # The secondary port serves the UI as well as health and debug endpoints. + - name: {{ $ports.http.name | quote }} + port: {{ $ports.http.port | int64 }} + targetPort: http + selector: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.public.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.public.yaml new file mode 100644 index 0000000000..251e9ab084 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/service.public.yaml @@ -0,0 +1,55 @@ +# This Service is meant to be used by clients of the database. +# It exposes a ClusterIP that will automatically load balance connections +# to the different database Pods. +kind: Service +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-public + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.service.public.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if or .Values.service.public.annotations .Values.tls.enabled .Values.iap.enabled }} + annotations: + {{- with .Values.service.public.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.tls.enabled }} + service.alpha.kubernetes.io/app-protocols: '{"http":"HTTPS"}' + {{- end }} + {{- if .Values.iap.enabled }} + beta.cloud.google.com/backend-config: '{"default": "{{ template "cockroachdb.fullname" . }}"}' + {{- end }} + {{- end }} +spec: + type: {{ .Values.service.public.type | quote }} + ports: + {{- $ports := .Values.service.ports }} + # The main port, served by gRPC, serves Postgres-flavor SQL, inter-node + # traffic and the CLI. + - name: {{ $ports.grpc.external.name | quote }} + port: {{ $ports.grpc.external.port | int64 }} + targetPort: grpc + {{- if ne ($ports.grpc.internal.port | int64) ($ports.grpc.external.port | int64) }} + - name: {{ $ports.grpc.internal.name | quote }} + port: {{ $ports.grpc.internal.port | int64 }} + targetPort: grpc + {{- end }} + # The secondary port serves the UI as well as health and debug endpoints. + - name: {{ $ports.http.name | quote }} + port: {{ $ports.http.port | int64 }} + targetPort: http + selector: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceMonitor.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceMonitor.yaml new file mode 100644 index 0000000000..42f2390b4c --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceMonitor.yaml @@ -0,0 +1,54 @@ +{{- $serviceMonitor := .Values.serviceMonitor -}} +{{- $ports := .Values.service.ports -}} +{{- if $serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- if $serviceMonitor.labels }} + {{- toYaml $serviceMonitor.labels | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if $serviceMonitor.annotations }} + annotations: + {{- toYaml $serviceMonitor.annotations | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.service.discovery.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + namespaceSelector: + {{- if $serviceMonitor.namespaced }} + matchNames: + - {{ .Release.Namespace }} + {{- else }} + any: true + {{- end }} + endpoints: + - port: {{ $ports.http.name | quote }} + path: /_status/vars + {{- if $serviceMonitor.interval }} + interval: {{ $serviceMonitor.interval }} + {{- end }} + {{- if $serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ $serviceMonitor.scrapeTimeout }} + {{- end }} + {{- if .Values.serviceMonitor.tlsConfig }} + tlsConfig: {{ toYaml .Values.serviceMonitor.tlsConfig | nindent 6 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certRotateSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certRotateSelfSigner.yaml new file mode 100644 index 0000000000..a27cba9219 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certRotateSelfSigner.yaml @@ -0,0 +1,22 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} + {{ template "cockroachdb.tls.certs.selfSigner.validation" . }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "rotatecerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.tls.certs.selfSigner.svcAccountAnnotations }} + annotations: + {{- with .Values.tls.certs.selfSigner.svcAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certSelfSigner.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certSelfSigner.yaml new file mode 100644 index 0000000000..3ce2d63e9e --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount-certSelfSigner.yaml @@ -0,0 +1,25 @@ +{{- if and .Values.tls.enabled .Values.tls.certs.selfSigner.enabled }} + {{ template "cockroachdb.tls.certs.selfSigner.validation" . }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "selfcerts.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + annotations: + # This is what defines this resource as a hook. Without this line, the + # job is considered part of the release. + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed + {{- with .Values.tls.certs.selfSigner.svcAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount.yaml new file mode 100644 index 0000000000..3af9be9aa9 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/serviceaccount.yaml @@ -0,0 +1,21 @@ +{{- if .Values.statefulset.serviceAccount.create }} +kind: ServiceAccount +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.serviceAccount.name" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .Values.statefulset.serviceAccount.annotations }} + annotations: + {{- with .Values.statefulset.serviceAccount.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/statefulset.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/statefulset.yaml new file mode 100644 index 0000000000..190d931a48 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/statefulset.yaml @@ -0,0 +1,402 @@ +kind: StatefulSet +apiVersion: {{ template "cockroachdb.statefulset.apiVersion" . }} +metadata: + name: {{ template "cockroachdb.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + helm.sh/chart: {{ template "cockroachdb.chart" . }} + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + app.kubernetes.io/managed-by: {{ .Release.Service | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + serviceName: {{ template "cockroachdb.fullname" . }} + replicas: {{ .Values.statefulset.replicas | int64 }} + updateStrategy: {{- toYaml .Values.statefulset.updateStrategy | nindent 4 }} + podManagementPolicy: {{ .Values.statefulset.podManagementPolicy | quote }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 6 }} + {{- end }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.statefulset.annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if or .Values.image.credentials (and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager)) }} + imagePullSecrets: + {{- if .Values.image.credentials }} + - name: {{ template "cockroachdb.fullname" . }}.db.registry + {{- end }} + {{- if and .Values.tls.enabled .Values.tls.selfSigner.image.credentials (not .Values.tls.certs.provided) (not .Values.tls.certs.certManager) }} + - name: {{ template "cockroachdb.fullname" . }}.self-signed-certs.registry + {{- end }} + {{- end }} + serviceAccountName: {{ template "cockroachdb.serviceAccount.name" . }} + {{- if .Values.tls.enabled }} + initContainers: + - name: copy-certs + image: {{ .Values.tls.copyCerts.image | quote }} + imagePullPolicy: {{ .Values.tls.selfSigner.image.pullPolicy | quote }} + command: + - /bin/sh + - -c + - "cp -f /certs/* /cockroach-certs/; chmod 0400 /cockroach-certs/*.key" + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + {{- if .Values.statefulset.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + {{- end }} + volumeMounts: + - name: certs + mountPath: /cockroach-certs/ + - name: certs-secret + mountPath: /certs/ + {{- with .Values.tls.copyCerts.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if or .Values.statefulset.nodeAffinity .Values.statefulset.podAffinity .Values.statefulset.podAntiAffinity }} + affinity: + {{- with .Values.statefulset.nodeAffinity }} + nodeAffinity: {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.statefulset.podAffinity }} + podAffinity: {{- toYaml . | nindent 10 }} + {{- end }} + {{- if .Values.statefulset.podAntiAffinity }} + podAntiAffinity: + {{- if .Values.statefulset.podAntiAffinity.type }} + {{- if eq .Values.statefulset.podAntiAffinity.type "hard" }} + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }} + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 18 }} + {{- end }} + {{- else if eq .Values.statefulset.podAntiAffinity.type "soft" }} + preferredDuringSchedulingIgnoredDuringExecution: + - weight: {{ .Values.statefulset.podAntiAffinity.weight | int64 }} + podAffinityTerm: + topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }} + labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 20 }} + {{- end }} + {{- end }} + {{- else }} + {{- toYaml .Values.statefulset.podAntiAffinity | nindent 10 }} + {{- end }} + {{- end }} + {{- end }} + {{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.Version }} + topologySpreadConstraints: + - labelSelector: + matchLabels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.statefulset.labels }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.statefulset.topologySpreadConstraints }} + maxSkew: {{ .maxSkew }} + topologyKey: {{ .topologyKey }} + whenUnsatisfiable: {{ .whenUnsatisfiable }} + {{- end }} + {{- end }} + {{- with .Values.statefulset.nodeSelector }} + nodeSelector: {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.statefulset.priorityClassName }} + priorityClassName: {{ .Values.statefulset.priorityClassName }} + {{- end }} + {{- with .Values.statefulset.tolerations }} + tolerations: {{- toYaml . | nindent 8 }} + {{- end }} + # No pre-stop hook is required, a SIGTERM plus some time is all that's + # needed for graceful shutdown of a node. + terminationGracePeriodSeconds: {{ .Values.init.terminationGracePeriodSeconds }} + containers: + - name: db + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + args: + - shell + - -ecx + # The use of qualified `hostname -f` is crucial: + # Other nodes aren't able to look up the unqualified hostname. + # + # `--join` CLI flag is hardcoded to exactly 3 Pods, because: + # 1. Having `--join` value depending on `statefulset.replicas` + # will trigger undesired restart of existing Pods when + # StatefulSet is scaled up/down. We want to scale without + # restarting existing Pods. + # 2. At least one Pod in `--join` is enough to successfully + # join CockroachDB cluster and gossip with all other existing + # Pods, even if there are 3 or more Pods. + # 3. It's harmless for `--join` to have 3 Pods even for 1-Pod + # clusters, while it gives us opportunity to scale up even if + # some Pods of existing cluster are down (for whatever reason). + # See details explained here: + # https://github.com/helm/charts/pull/18993#issuecomment-558795102 + - >- + exec /cockroach/cockroach + {{- if index .Values.conf `single-node` }} + start-single-node + {{- else }} + start --join= + {{- if .Values.conf.join }} + {{- join `,` .Values.conf.join -}} + {{- else }} + {{- range $i, $_ := until 3 -}} + {{- if gt $i 0 -}},{{- end -}} + ${STATEFULSET_NAME}-{{ $i }}.${STATEFULSET_FQDN}:{{ $.Values.service.ports.grpc.internal.port | int64 -}} + {{- end -}} + {{- end }} + {{- with index .Values.conf `cluster-name` }} + --cluster-name={{ . }} + {{- if index $.Values.conf `disable-cluster-name-verification` }} + --disable-cluster-name-verification + {{- end }} + {{- end }} + {{- end }} + --advertise-host=$(hostname).${STATEFULSET_FQDN} + {{- if .Values.tls.enabled }} + --certs-dir=/cockroach/cockroach-certs/ + {{- else }} + --insecure + {{- end }} + {{- with .Values.conf.attrs }} + --attrs={{ join `:` . }} + {{- end }} + --http-port={{ index .Values.conf `http-port` | int64 }} + --port={{ .Values.conf.port | int64 }} + --cache={{ .Values.conf.cache }} + {{- with index .Values.conf `max-disk-temp-storage` }} + --max-disk-temp-storage={{ . }} + {{- end }} + {{- with index .Values.conf `max-offset` }} + --max-offset={{ . }} + {{- end }} + --max-sql-memory={{ index .Values.conf `max-sql-memory` }} + {{- with .Values.conf.locality }} + --locality={{ . }} + {{- end }} + {{- with index .Values.conf `sql-audit-dir` }} + --sql-audit-dir={{ . }} + {{- end }} + {{- if .Values.conf.store.enabled }} + --store={{ template "cockroachdb.conf.store" . }} + {{- end }} + {{- if .Values.conf.log.enabled }} + --log-config-file=/cockroach/log-config/log-config.yaml + {{- else }} + --logtostderr={{ .Values.conf.logtostderr }} + {{- end }} + {{- range .Values.statefulset.args }} + {{ . }} + {{- end }} + env: + - name: STATEFULSET_NAME + value: {{ template "cockroachdb.fullname" . }} + - name: STATEFULSET_FQDN + value: {{ template "cockroachdb.fullname" . }}.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }} + - name: COCKROACH_CHANNEL + value: kubernetes-helm + {{- with .Values.statefulset.env }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: grpc + containerPort: {{ .Values.conf.port | int64 }} + protocol: TCP + - name: http + containerPort: {{ index .Values.conf `http-port` | int64 }} + protocol: TCP + volumeMounts: + - name: datadir + mountPath: /cockroach/{{ .Values.conf.path }}/ + {{- if .Values.tls.enabled }} + - name: certs + mountPath: /cockroach/cockroach-certs/ + {{- if .Values.tls.certs.provided }} + - name: certs-secret + mountPath: /cockroach/certs/ + {{- end }} + {{- end }} + {{- range .Values.statefulset.secretMounts }} + - name: {{ printf "secret-%s" . | quote }} + mountPath: {{ printf "/etc/cockroach/secrets/%s" . | quote }} + readOnly: true + {{- end }} + {{- if .Values.conf.log.enabled }} + - name: log-config + mountPath: /cockroach/log-config + readOnly: true + {{- end }} + livenessProbe: + {{- if .Values.statefulset.customLivenessProbe }} + {{ toYaml .Values.statefulset.customLivenessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health + port: http + {{- if .Values.tls.enabled }} + scheme: HTTPS + {{- end }} + initialDelaySeconds: 30 + periodSeconds: 5 + {{- end }} + readinessProbe: + {{- if .Values.statefulset.customReadinessProbe }} + {{ toYaml .Values.statefulset.customReadinessProbe | nindent 12 }} + {{- else }} + httpGet: + path: /health?ready=1 + port: http + {{- if .Values.tls.enabled }} + scheme: HTTPS + {{- end }} + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 2 + {{- end }} + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if .Values.statefulset.securityContext.enabled }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + {{- end }} + {{- end }} + {{- with .Values.statefulset.resources }} + resources: {{- toYaml . | nindent 12 }} + {{- end }} + volumes: + - name: datadir + {{- if .Values.storage.persistentVolume.enabled }} + persistentVolumeClaim: + claimName: datadir + {{- else if .Values.storage.hostPath }} + hostPath: + path: {{ .Values.storage.hostPath | quote }} + {{- else }} + emptyDir: {} + {{- end }} + {{- if .Values.tls.enabled }} + - name: certs + emptyDir: {} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + - name: certs-secret + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager .Values.tls.certs.selfSigner.enabled }} + projected: + sources: + - secret: + {{- if .Values.tls.certs.selfSigner.enabled }} + name: {{ template "cockroachdb.fullname" . }}-node-secret + {{ else }} + name: {{ .Values.tls.certs.nodeSecret }} + {{ end -}} + items: + - key: ca.crt + path: ca.crt + mode: 256 + - key: tls.crt + path: node.crt + mode: 256 + - key: tls.key + path: node.key + mode: 256 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.nodeSecret }} + defaultMode: 256 + {{- end }} + {{- end }} + {{- end }} + {{- range .Values.statefulset.secretMounts }} + - name: {{ printf "secret-%s" . | quote }} + secret: + secretName: {{ . | quote }} + {{- end }} + {{- if .Values.conf.log.enabled }} + - name: log-config + secret: + secretName: {{ template "cockroachdb.fullname" . }}-log-config + {{- end }} + {{- if eq (include "cockroachdb.securityContext.versionValidation" .) "true" }} + {{- if and .Values.securityContext.enabled }} + securityContext: + seccompProfile: + type: "RuntimeDefault" + fsGroup: 1000 + runAsGroup: 1000 + runAsUser: 1000 + runAsNonRoot: true + {{- end }} + {{- end }} +{{- if .Values.storage.persistentVolume.enabled }} + volumeClaimTemplates: + - metadata: + name: datadir + labels: + app.kubernetes.io/name: {{ template "cockroachdb.name" . }} + app.kubernetes.io/instance: {{ .Release.Name | quote }} + {{- with .Values.storage.persistentVolume.labels }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.labels }} + {{- toYaml . | nindent 10 }} + {{- end }} + {{- with .Values.storage.persistentVolume.annotations }} + annotations: {{- toYaml . | nindent 10 }} + {{- end }} + spec: + accessModes: ["ReadWriteOnce"] + {{- if .Values.storage.persistentVolume.storageClass }} + {{- if (eq "-" .Values.storage.persistentVolume.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.storage.persistentVolume.storageClass | quote}} + {{- end }} + {{- end }} + resources: + requests: + storage: {{ .Values.storage.persistentVolume.size | quote }} +{{- end }} diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/templates/tests/client.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/templates/tests/client.yaml new file mode 100644 index 0000000000..8656b8ed68 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/templates/tests/client.yaml @@ -0,0 +1,65 @@ +kind: Pod +apiVersion: v1 +metadata: + name: {{ template "cockroachdb.fullname" . }}-test + namespace: {{ .Release.Namespace | quote }} +{{- if .Values.networkPolicy.enabled }} + labels: + {{ template "cockroachdb.fullname" . }}-client: "true" +{{- end }} + annotations: + helm.sh/hook: test-success +spec: + restartPolicy: Never +{{- if .Values.image.credentials }} + imagePullSecrets: + - name: {{ template "cockroachdb.fullname" . }}.db.registry +{{- end }} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + volumes: + - name: client-certs + {{- if or .Values.tls.certs.tlsSecret .Values.tls.certs.certManager }} + projected: + sources: + - secret: + name: {{ .Values.tls.certs.clientRootSecret }} + items: + - key: ca.crt + path: ca.crt + mode: 0400 + - key: tls.crt + path: client.root.crt + mode: 0400 + - key: tls.key + path: client.root.key + mode: 0400 + {{- else }} + secret: + secretName: {{ .Values.tls.certs.clientRootSecret }} + defaultMode: 0400 + {{- end }} + {{- end }} + containers: + - name: client-test + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy | quote }} + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + volumeMounts: + - name: client-certs + mountPath: /cockroach-certs + {{- end }} + command: + - /cockroach/cockroach + - sql + {{- if or .Values.tls.certs.provided .Values.tls.certs.certManager }} + - --certs-dir + - /cockroach-certs + {{- else }} + - --insecure + {{- end}} + - --host + - {{ template "cockroachdb.fullname" . }}-public.{{ .Release.Namespace }} + - --port + - {{ .Values.service.ports.grpc.external.port | quote }} + - -e + - SHOW DATABASES; diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/values.schema.json b/charts/cockroach-labs/cockroachdb/14.0.3/values.schema.json new file mode 100644 index 0000000000..b23c479741 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/values.schema.json @@ -0,0 +1,97 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "properties": { + "tls": { + "type": "object", + "properties": { + "certs": { + "type": "object", + "properties": { + "selfSigner": { + "type": "object", + "required": ["enabled", "caProvided"], + "properties": { + "enabled": { + "type": "boolean" + }, + "caProvided": { + "type": "boolean" + } + }, + "if": { + "properties": { + "enabled": { + "const": true + } + } + }, + "then": { + "if": { + "properties": { + "caProvided": { + "const": false + } + } + }, + "then": { + "properties": { + "caCertDuration" : { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "caCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + } + } + }, + "properties": { + "clientCertDuration": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "clientCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "nodeCertDuration": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "nodeCertExpiryWindow": { + "type": "string", + "pattern": "^[0-9]*h$" + }, + "rotateCerts": { + "type": "boolean" + } + } + } + } + } + }, + "selfSigner": { + "type": "object", + "properties": { + "image": { + "type": "object", + "required": ["repository", "tag", "pullPolicy"], + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "pullPolicy": { + "type": "string", + "pattern": "^(Always|Never|IfNotPresent)$" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/charts/cockroach-labs/cockroachdb/14.0.3/values.yaml b/charts/cockroach-labs/cockroachdb/14.0.3/values.yaml new file mode 100644 index 0000000000..10c63298d5 --- /dev/null +++ b/charts/cockroach-labs/cockroachdb/14.0.3/values.yaml @@ -0,0 +1,606 @@ +# Generated file, DO NOT EDIT. Source: build/templates/values.yaml +# Overrides the chart name against the label "app.kubernetes.io/name: " placed on every resource this chart creates. +nameOverride: "" + +# Override the resource names created by this chart which originally is generated using release and chart name. +fullnameOverride: "" + +image: + repository: cockroachdb/cockroach + tag: v24.2.2 + pullPolicy: IfNotPresent + credentials: {} + # registry: docker.io + # username: john_doe + # password: changeme + + +# Additional labels to apply to all Kubernetes resources created by this chart. +labels: {} + # app.kubernetes.io/part-of: my-app + + +# Cluster's default DNS domain. +# You should overwrite it if you're using a different one, +# otherwise CockroachDB nodes discovery won't work. +clusterDomain: cluster.local + + +conf: + # An ordered list of CockroachDB node attributes. + # Attributes are arbitrary strings specifying machine capabilities. + # Machine capabilities might include specialized hardware or number of cores + # (e.g. "gpu", "x16c"). + attrs: [] + # - x16c + # - gpu + + # Total size in bytes for caches, shared evenly if there are multiple + # storage devices. Size suffixes are supported (e.g. `1GB` and `1GiB`). + # A percentage of physical memory can also be specified (e.g. `.25`). + cache: 25% + + # Sets a name to verify the identity of a cluster. + # The value must match between all nodes specified via `conf.join`. + # This can be used as an additional verification when either the node or + # cluster, or both, have not yet been initialized and do not yet know their + # cluster ID. + # To introduce a cluster name into an already-initialized cluster, pair this + # option with `conf.disable-cluster-name-verification: yes`. + cluster-name: "" + + # Tell the server to ignore `conf.cluster-name` mismatches. + # This is meant for use when opting an existing cluster into starting to use + # cluster name verification, or when changing the cluster name. + # The cluster should be restarted once with `conf.cluster-name` and + # `conf.disable-cluster-name-verification: yes` combined, and once all nodes + # have been updated to know the new cluster name, the cluster can be restarted + # again with `conf.disable-cluster-name-verification: no`. + # This option has no effect if `conf.cluster-name` is not specified. + disable-cluster-name-verification: false + + # The addresses for connecting a CockroachDB nodes to an existing cluster. + # If you are deploying a second CockroachDB instance that should join a first + # one, use the below list to join to the existing instance. + # Each item in the array should be a FQDN (and port if needed) resolvable by + # new Pods. + join: [] + + # New logging configuration. + log: + enabled: false + # https://www.cockroachlabs.com/docs/v21.1/configure-logs + config: {} + # file-defaults: + # dir: /custom/dir/path/ + # fluent-defaults: + # format: json-fluent + # sinks: + # stderr: + # channels: [DEV] + + # Logs at or above this threshold to STDERR. Ignored when "log" is enabled + logtostderr: INFO + + # Maximum storage capacity available to store temporary disk-based data for + # SQL queries that exceed the memory budget (e.g. join, sorts, etc are + # sometimes able to spill intermediate results to disk). + # Accepts numbers interpreted as bytes, size suffixes (e.g. `32GB` and + # `32GiB`) or a percentage of disk size (e.g. `10%`). + # The location of the temporary files is within the first store dir. + # If expressed as a percentage, `max-disk-temp-storage` is interpreted + # relative to the size of the storage device on which the first store is + # placed. The temp space usage is never counted towards any store usage + # (although it does share the device with the first store) so, when + # configuring this, make sure that the size of this temp storage plus the size + # of the first store don't exceed the capacity of the storage device. + # If the first store is an in-memory one (i.e. `type=mem`), then this + # temporary "disk" data is also kept in-memory. + # A percentage value is interpreted as a percentage of the available internal + # memory. + # max-disk-temp-storage: 0GB + + # Maximum allowed clock offset for the cluster. If observed clock offsets + # exceed this limit, servers will crash to minimize the likelihood of + # reading inconsistent data. Increasing this value will increase the time + # to recovery of failures as well as the frequency of uncertainty-based + # read restarts. + # Note, that this value must be the same on all nodes in the cluster. + # In order to change it, all nodes in the cluster must be stopped + # simultaneously and restarted with the new value. + # max-offset: 500ms + + # Maximum memory capacity available to store temporary data for SQL clients, + # including prepared queries and intermediate data rows during query + # execution. Accepts numbers interpreted as bytes, size suffixes + # (e.g. `1GB` and `1GiB`) or a percentage of physical memory (e.g. `.25`). + max-sql-memory: 25% + + # An ordered, comma-separated list of key-value pairs that describe the + # topography of the machine. Topography might include country, datacenter + # or rack designations. Data is automatically replicated to maximize + # diversities of each tier. The order of tiers is used to determine + # the priority of the diversity, so the more inclusive localities like + # country should come before less inclusive localities like datacenter. + # The tiers and order must be the same on all nodes. Including more tiers + # is better than including fewer. For example: + # locality: country=us,region=us-west,datacenter=us-west-1b,rack=12 + # locality: country=ca,region=ca-east,datacenter=ca-east-2,rack=4 + # locality: planet=earth,province=manitoba,colo=secondary,power=3 + locality: "" + + # Run CockroachDB instances in standalone mode with replication disabled + # (replication factor = 1). + # Enabling this option makes the following values to be ignored: + # - `conf.cluster-name` + # - `conf.disable-cluster-name-verification` + # - `conf.join` + # + # WARNING: Enabling this option makes each deployed Pod as a STANDALONE + # CockroachDB instance, so the StatefulSet does NOT FORM A CLUSTER. + # Don't use this option for production deployments unless you clearly + # understand what you're doing. + # Usually, this option is intended to be used in conjunction with + # `statefulset.replicas: 1` for temporary one-time deployments (like + # running E2E tests, for example). + single-node: false + + # If non-empty, create a SQL audit log in the specified directory. + sql-audit-dir: "" + + # CockroachDB's port to listen to inter-communications and client connections. + port: 26257 + + # CockroachDB's port to listen to HTTP requests. + http-port: 8080 + + # CockroachDB's data mount path. + path: cockroach-data + + # CockroachDB's storage configuration https://www.cockroachlabs.com/docs/v21.1/cockroach-start.html#storage + # Uses --store flag + store: + enabled: false + # Should be empty or 'mem' + type: + # Required for type=mem. If type and size is empty - storage.persistentVolume.size is used + size: + # Arbitrary strings, separated by colons, specifying disk type or capability + attrs: + +statefulset: + replicas: 3 + updateStrategy: + type: RollingUpdate + podManagementPolicy: Parallel + budget: + maxUnavailable: 1 + + # List of additional command-line arguments you want to pass to the + # `cockroach start` command. + args: [] + # - --disable-cluster-name-verification + + # List of extra environment variables to pass into container + env: [] + # - name: COCKROACH_ENGINE_MAX_SYNC_DURATION + # value: "24h" + + # List of Secrets names in the same Namespace as the CockroachDB cluster, + # which shall be mounted into `/etc/cockroach/secrets/` for every cluster + # member. + secretMounts: [] + + # Additional labels to apply to this StatefulSet and all its Pods. + labels: + app.kubernetes.io/component: cockroachdb + + # Additional annotations to apply to the Pods of this StatefulSet. + annotations: {} + + # Affinity rules for scheduling Pods of this StatefulSet on Nodes. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + nodeAffinity: {} + # Inter-Pod Affinity rules for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity + podAffinity: {} + # Anti-affinity rules for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity + # You may either toggle options below for default anti-affinity rules, + # or specify the whole set of anti-affinity rules instead of them. + podAntiAffinity: + # The topologyKey to be used. + # Can be used to spread across different nodes, AZs, regions etc. + topologyKey: kubernetes.io/hostname + # Type of anti-affinity rules: either `soft`, `hard` or empty value (which + # disables anti-affinity rules). + type: soft + # Weight for `soft` anti-affinity rules. + # Does not apply for other anti-affinity types. + weight: 100 + + # Node selection constraints for scheduling Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # PriorityClassName given to Pods of this StatefulSet + # https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass + priorityClassName: "" + + # Taints to be tolerated by Pods of this StatefulSet. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/ + topologySpreadConstraints: + maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway + + # Uncomment the following resources definitions or pass them from + # command line to control the CPU and memory resources allocated + # by Pods of this StatefulSet. + resources: {} + # limits: + # cpu: 100m + # memory: 512Mi + # requests: + # cpu: 100m + # memory: 512Mi + + # terminationGracePeriodSeconds is the duration in seconds the Pod needs to terminate gracefully. + terminationGracePeriodSeconds: 300 + + # Custom Liveness probe + # https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request + customLivenessProbe: {} + # httpGet: + # path: /health + # port: http + # scheme: HTTPS + # initialDelaySeconds: 30 + # periodSeconds: 5 + + # Custom Rediness probe + # https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-readiness-probes + customReadinessProbe: {} + # httpGet: + # path: /health + # port: http + # scheme: HTTPS + # initialDelaySeconds: 30 + # periodSeconds: 5 + + securityContext: + enabled: true + + serviceAccount: + # Specifies whether this ServiceAccount should be created. + create: true + # The name of this ServiceAccount to use. + # If not set and `create` is `true`, then service account is auto-generated. + # If not set and `create` is `false`, then it uses default service account. + name: "" + # Additional serviceAccount annotations (e.g. for attaching AWS IAM roles to pods) + annotations: {} + +service: + ports: + # You can set a different external and internal gRPC ports and their name. + grpc: + external: + port: 26257 + name: grpc + # If the port number is different than `external.port`, then it will be + # named as `internal.name` in Service. + internal: + port: 26257 + # If using Istio set it to `cockroach`. + name: grpc-internal + http: + port: 8080 + name: http + + # This Service is meant to be used by clients of the database. + # It exposes a ClusterIP that will automatically load balance connections + # to the different database Pods. + public: + type: ClusterIP + # Additional labels to apply to this Service. + labels: + app.kubernetes.io/component: cockroachdb + # Additional annotations to apply to this Service. + annotations: {} + + # This service only exists to create DNS entries for each pod in + # the StatefulSet such that they can resolve each other's IP addresses. + # It does not create a load-balanced ClusterIP and should not be used directly + # by clients in most circumstances. + discovery: + # Additional labels to apply to this Service. + labels: + app.kubernetes.io/component: cockroachdb + # Additional annotations to apply to this Service. + annotations: {} + +# CockroachDB's ingress for web ui. +ingress: + enabled: false + labels: {} + annotations: {} + # kubernetes.io/ingress.class: nginx + # cert-manager.io/cluster-issuer: letsencrypt + paths: [/] + hosts: [] + # - cockroachlabs.com + tls: [] + # - hosts: [cockroachlabs.com] + # secretName: cockroachlabs-tls + +prometheus: + enabled: true + +securityContext: + enabled: true + +# CockroachDB's Prometheus operator ServiceMonitor support +serviceMonitor: + enabled: false + labels: {} + annotations: {} + interval: 10s + # scrapeTimeout: 10s + # Limits the ServiceMonitor to the current namespace if set to `true`. + namespaced: false + + # tlsConfig: TLS configuration to use when scraping the endpoint. + # Of type: https://github.com/coreos/prometheus-operator/blob/main/Documentation/api.md#tlsconfig + tlsConfig: {} + +# CockroachDB's data persistence. +# If neither `persistentVolume` nor `hostPath` is used, then data will be +# persisted in ad-hoc `emptyDir`. +storage: + # Absolute path on host to store CockroachDB's data. + # If not specified, then `emptyDir` will be used instead. + # If specified, but `persistentVolume.enabled` is `true`, then has no effect. + hostPath: "" + + # If `enabled` is `true` then a PersistentVolumeClaim will be created and + # used to store CockroachDB's data, otherwise `hostPath` is used. + persistentVolume: + enabled: true + + size: 100Gi + + # If defined, then `storageClassName: `. + # If set to "-", then `storageClassName: ""`, which disables dynamic + # provisioning. + # If undefined or empty (default), then no `storageClassName` spec is set, + # so the default provisioner will be chosen (gp2 on AWS, standard on + # GKE, AWS & OpenStack). + storageClass: "" + + # Additional labels to apply to the created PersistentVolumeClaims. + labels: {} + # Additional annotations to apply to the created PersistentVolumeClaims. + annotations: {} + + +# Kubernetes Job which initializes multi-node CockroachDB cluster. +# It's not created if `statefulset.replicas` is `1`. +init: + # Additional labels to apply to this Job and its Pod. + labels: + app.kubernetes.io/component: init + + # Additional annotations to apply to this Job. + jobAnnotations: {} + + # Additional annotations to apply to the Pod of this Job. + annotations: {} + + # Affinity rules for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + + # Node selection constraints for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # Taints to be tolerated by the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # The init Pod runs at cluster creation to initialize CockroachDB. It finishes + # quickly and doesn't continue to consume resources in the Kubernetes + # cluster. Normally, you should leave this section commented out, but if your + # Kubernetes cluster uses Resource Quotas and requires all pods to specify + # resource requests or limits, you can set those here. + resources: {} + # requests: + # cpu: "10m" + # memory: "128Mi" + # limits: + # cpu: "10m" + # memory: "128Mi" + + # terminationGracePeriodSeconds is the duration in seconds the Pod needs to terminate gracefully. + terminationGracePeriodSeconds: 300 + + securityContext: + enabled: true + + # Setup Physical Cluster Replication (PCR) between primary and standby cluster. + # If isPrimary is set to true, the CockroachDB cluster created is the primary cluster. + # If isPrimary is set to false, the CockroachDB cluster created is the standby cluster. + pcr: + enabled: false + # isPrimary: true + + provisioning: + enabled: false + # https://www.cockroachlabs.com/docs/stable/cluster-settings.html + clusterSettings: + # cluster.organization: "'FooCorp - Local Testing'" + # enterprise.license: "'xxxxx'" + users: [] + # - name: + # password: + # # https://www.cockroachlabs.com/docs/stable/create-user.html#parameters + # options: [LOGIN] + databases: [] + # - name: + # # https://www.cockroachlabs.com/docs/stable/create-database.html#parameters + # options: [encoding='utf-8'] + # owners: [] + # # https://www.cockroachlabs.com/docs/stable/grant.html#parameters + # owners_with_grant_option: [] + # # Backup schedules are not idemponent for now and will fail on next run + # # https://github.com/cockroachdb/cockroach/issues/57892 + # backup: + # into: s3:// + # # Enterprise-only option (revision_history) + # # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#backup-options + # options: [revision_history] + # recurring: '@always' + # # Enterprise-only feature. Remove this value to use `FULL BACKUP ALWAYS` + # fullBackup: '@daily' + # schedule: + # # https://www.cockroachlabs.com/docs/stable/create-schedule-for-backup.html#schedule-options + # options: [first_run = 'now'] + + +# Whether to run securely using TLS certificates. +tls: + enabled: true + copyCerts: + image: busybox + certs: + # Bring your own certs scenario. If provided, tls.init section will be ignored. + provided: false + # Secret name for the client root cert. + clientRootSecret: cockroachdb-root + # Secret name for node cert. + nodeSecret: cockroachdb-node + # Secret name for CA cert + caSecret: cockroach-ca + # Enable if the secret is a dedicated TLS. + # TLS secrets are created by cert-mananger, for example. + tlsSecret: false + # Enable if the you want cockroach db to create its own certificates + selfSigner: + # If set, the cockroach db will generate its own certificates + enabled: true + # Run selfSigner as non-root + securityContext: + enabled: true + # If set, the user should provide the CA certificate to sign other certificates. + caProvided: false + # It holds the name of the secret with caCerts. If caProvided is set, this can not be empty. + caSecret: "" + # Minimum Certificate duration for all the certificates, all certs duration will be validated against this. + minimumCertDuration: 624h + # Duration of CA certificates in hour + caCertDuration: 43800h + # Expiry window of CA certificates means a window before actual expiry in which CA certs should be rotated. + caCertExpiryWindow: 648h + # Duration of Client certificates in hour + clientCertDuration: 672h + # Expiry window of client certificates means a window before actual expiry in which client certs should be rotated. + clientCertExpiryWindow: 48h + # Duration of node certificates in hour + nodeCertDuration: 8760h + # Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. + nodeCertExpiryWindow: 168h + # If set, the cockroachdb cert selfSigner will rotate the certificates before expiry. + rotateCerts: true + # Wait time for each cockroachdb replica to become ready once it comes in running state. Only considered when rotateCerts is set to true + readinessWait: 30s + # Wait time for each cockroachdb replica to get to running state. Only considered when rotateCerts is set to true + podUpdateTimeout: 2m + # ServiceAccount annotations for selfSigner jobs (e.g. for attaching AWS IAM roles to pods) + svcAccountAnnotations: {} + + # Use cert-manager to issue certificates for mTLS. + certManager: false + # Specify an Issuer or a ClusterIssuer to use, when issuing + # node and client certificates. The values correspond to the + # issuerRef specified in the certificate. + certManagerIssuer: + group: cert-manager.io + kind: Issuer + name: cockroachdb + # Make it false when you are providing your own CA issuer + isSelfSignedIssuer: true + # Duration of CA certificates in hour + caCertDuration: 43800h + # Expiry window of CA certificates means a window before actual expiry in which CA certs should be rotated. + caCertExpiryWindow: 648h + # Duration of Client certificates in hours + clientCertDuration: 672h + # Expiry window of client certificates means a window before actual expiry in which client certs should be rotated. + clientCertExpiryWindow: 48h + # Duration of node certificates in hours + nodeCertDuration: 8760h + # Expiry window of node certificates means a window before actual expiry in which node certs should be rotated. + nodeCertExpiryWindow: 168h + + selfSigner: + # Additional labels to apply to the Pod of this Job. + labels: {} + + # Additional annotations to apply to the Pod of this Job. + annotations: {} + + # Affinity rules for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity + affinity: {} + + # Node selection constraints for scheduling the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + + # Taints to be tolerated by the Pod of this Job. + # https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ + tolerations: [] + + # Image Placeholder for the selfSigner utility. This will be changed once the CI workflows for the image is in place. + image: + repository: cockroachlabs-helm-charts/cockroach-self-signer-cert + tag: "1.5" + pullPolicy: IfNotPresent + credentials: {} + registry: gcr.io + # username: john_doe + # password: changeme + +networkPolicy: + enabled: false + + ingress: + # List of sources which should be able to access the CockroachDB Pods via + # gRPC port. Items in this list are combined using a logical OR operation. + # Rules for allowing inter-communication are applied automatically. + # If empty, then connections from any Pod is allowed. + grpc: [] + # - podSelector: + # matchLabels: + # app.kubernetes.io/name: my-app-django + # app.kubernetes.io/instance: my-app + + # List of sources which should be able to access the CockroachDB Pods via + # HTTP port. Items in this list are combined using a logical OR operation. + # If empty, then connections from any Pod is allowed. + http: [] + # - namespaceSelector: + # matchLabels: + # project: my-project + +# To put the admin interface behind Identity Aware Proxy (IAP) on Google Cloud Platform +# make sure to set ingress.paths: ['/*'] +iap: + enabled: false + # Create Google Cloud OAuth credentials and set client id and secret + # clientId: + # clientSecret: diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/.helmignore b/charts/dynatrace/dynatrace-operator/1.3.0/.helmignore new file mode 100644 index 0000000000..98229532e0 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/.helmignore @@ -0,0 +1,25 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ + +tests/ diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/Chart.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/Chart.yaml new file mode 100644 index 0000000000..4db82bebce --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/Chart.yaml @@ -0,0 +1,23 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Dynatrace Operator + catalog.cattle.io/kube-version: '>=1.19.0-0' + catalog.cattle.io/release-name: dynatrace-operator +apiVersion: v2 +appVersion: 1.3.0 +description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift +home: https://www.dynatrace.com/ +icon: file://assets/icons/dynatrace-operator.png +kubeVersion: '>=1.19.0-0' +maintainers: +- email: marcell.sevcsik@dynatrace.com + name: 0sewa0 +- email: christoph.muellner@dynatrace.com + name: chrismuellner +- email: lukas.hinterreiter@dynatrace.com + name: luhi-DT +name: dynatrace-operator +sources: +- https://github.com/Dynatrace/dynatrace-operator +type: application +version: 1.3.0 diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/README.md b/charts/dynatrace/dynatrace-operator/1.3.0/README.md new file mode 100644 index 0000000000..97a98a0189 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/README.md @@ -0,0 +1,48 @@ +# Dynatrace Operator Helm Chart + +The Dynatrace Operator supports rollout and lifecycle of various Dynatrace components in Kubernetes and OpenShift. + +This Helm Chart requires Helm 3. + +## Quick Start + +Migration instructions can be found in the [official help page](https://www.dynatrace.com/support/help/shortlink/k8s-dto-helm#migrate). + +Install the Dynatrace Operator via Helm by running the following commands. + +### Installation + +> For instructions on how to install the dynatrace-operator on Openshift, head to the +> [official help page](https://www.dynatrace.com/support/help/shortlink/k8s-helm) + +#### For versions older than 0.15.0 + +Add `dynatrace` helm repository: + +```console +helm repo add dynatrace https://raw.githubusercontent.com/Dynatrace/dynatrace-operator/main/config/helm/repos/stable +``` + +Install `dynatrace-operator` helm chart and create the corresponding `dynatrace` namespace: + +```console +helm install dynatrace-operator dynatrace/dynatrace-operator -n dynatrace --create-namespace --atomic +``` + +#### For versions 0.15.0 and after + +Install `dynatrace-operator` helm chart using the OCI repository and create the corresponding `dynatrace` namespace: + +```console +helm install dynatrace-operator oci://public.ecr.aws/dynatrace/dynatrace-operator -n dynatrace --create-namespace --atomic +``` + +## Uninstall chart + +> Full instructions can be found in the [official help page](https://www.dynatrace.com/support/help/shortlink/k8s-helm#uninstall-dynatrace-operator) + +Uninstall the Dynatrace Operator by running the following command: + +```console +helm uninstall dynatrace-operator -n dynatrace +``` diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/app-readme.md b/charts/dynatrace/dynatrace-operator/1.3.0/app-readme.md new file mode 100644 index 0000000000..844c96dd77 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/app-readme.md @@ -0,0 +1,5 @@ +# Dynatrace Operator + +The Dynatrace Operator supports rollout and lifecycle of various Dynatrace components in Kubernetes and OpenShift. + +As of launch, the Dynatrace Operator can be used to deploy a containerized ActiveGate for Kubernetes API monitoring. New capabilities will be added to the Dynatrace Operator over time including metric routing, and API monitoring for AWS, Azure, GCP, and vSphere. diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/logo.png b/charts/dynatrace/dynatrace-operator/1.3.0/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..6714eb8a59509d9513133b43b2de290f73be9c18 GIT binary patch literal 9908 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 R5fVsXi>>{}+<&~z{~v%ki3tDz literal 0 HcmV?d00001 diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/questions.yml b/charts/dynatrace/dynatrace-operator/1.3.0/questions.yml new file mode 100644 index 0000000000..70c94f9da0 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/questions.yml @@ -0,0 +1,236 @@ +categories: + - APM + - Monitoring +questions: + + #################### Global Configuration #################### + - variable: installCRD + label: "Install Custom Resource Definitions" + description: "Installs the Custom Resource Definitions for the Dynakube. This is recommended if you haven't installed it manually yet. Default: true" + default: true + type: boolean + group: "Global Configuration" + + - variable: image + label: "Set a custom image for operator components" + description: "Set a custom image for operator. Defaults to public.ecr.aws/dynatrace/dynatrace-operator" + default: "" + type: string + group: "Global Configuration" + + - variable: customPullSecret + label: "Set a custom pull secret for operator image" + description: "Set a custom pull secret for the operator image" + default: "" + type: string + group: "Global Configuration" + + #################### Operator Deployment Configuration #################### + - variable: operator.nodeSelector + label: "Assign the Dynatrace Operator's pod to certain nodes" + description: "Defines a NodeSelector to customize to which nodes the Dynatrace Operator can be deployed on - Please edit as Yaml for the best experience - see https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector" + default: "" + type: string + group: "Operator Deployment Configuration" + + - variable: operator.tolerations + label: "Custom tolerations for the Dynatrace Operator's pod" + description: "Defines custom tolerations to the Dynatrace Operator - Please edit as Yaml for the best experience - see https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/" + default: "" + type: string + group: "Operator Deployment Configuration" + + - variable: operator.apparmor + label: "Enable AppArmor for the Dynatrace Operator's pod" + description: "Adds AppArmor security annotations to the Dynatrace Operator's pod. Default: false" + default: false + type: boolean + group: "Operator Deployment Configuration" + + - variable: operator.requests.cpu + label: "CPU resource requests settings for Dynatrace Operator's pods" + description: "The minimum amount of CPU resources that the Dynatrace Operator's pods should request. Affects scheduling. Default: 50m" + default: "50m" + type: string + group: "Operator Deployment Configuration" + + - variable: operator.requests.memory + label: "Memory resource requests settings for Dynatrace Operator's pods" + description: "The minimum amount of memory that the Dynatrace Operator's pods should request. Affects scheduling. Default: 64Mi" + default: "64Mi" + type: string + group: "Operator Deployment Configuration" + + - variable: operator.limits.cpu + label: "CPU resource limits settings for Dynatrace Operator's pods" + description: "The maximum amount of CPU resources that the Dynatrace Operator's pods can use. Default: 100m" + default: "100m" + type: string + group: "Operator Deployment Configuration" + + - variable: operator.limits.memory + label: "Memory resource limits settings for Dynatrace Operator's pods" + description: "The maximum amount of memory that the Dynatrace Operator's pods can use. Pod restarted if exceeded. Default: 128Mi" + default: "128Mi" + type: string + group: "Operator Deployment Configuration" + + + #################### Webhook Deployment Configuration #################### + + - variable: webhook.apparmor + label: "Enable AppArmor for the Dynatrace Webhook's pod" + description: "Adds AppArmor security annotations to the Dynatrace Webhook's pod. Default: false" + default: false + type: boolean + group: "Webhook Deployment Configuration" + + - variable: webhook.highAvailability + label: "Enable high availability for the Dynatrace Webhook's pod" + description: "Adds topologySpreadConstraints and increases the replicas to 2 for the Dynatrace Webhook's pod. Default: false" + default: false + type: boolean + group: "Webhook Deployment Configuration" + + - variable: webhook.hostNetwork + label: "Enable hostNetwork for the Dynatrace Webhook's pod" + description: "Enables hostNetwork for the Dynatrace Webhook's pod. Default: false" + default: false + type: boolean + group: "Webhook Deployment Configuration" + + - variable: webhook.requests.cpu + label: "CPU resource requests settings for Dynatrace Webhook's pods" + description: "The minimum amount of CPU resources that the Dynatrace Webhook's pods should request. Affects scheduling. Default: 300m" + default: "300m" + type: string + group: "Webhook Deployment Configuration" + + - variable: webhook.requests.memory + label: "Memory resource requests settings for Dynatrace Webhook's pods" + description: "The minimum amount of memory that the Dynatrace Webhook's pods should request. Affects scheduling. Default: 128Mi" + default: "128Mi" + type: string + group: "Webhook Deployment Configuration" + + - variable: webhook.limits.cpu + label: "CPU resource limits settings for Dynatrace Webhook's pods" + description: "The maximum amount of CPU resources that the Dynatrace Webhook's pods can use. Default: 300m" + default: "300m" + type: string + group: "Webhook Deployment Configuration" + + - variable: webhook.limits.memory + label: "Memory resource limits settings for Dynatrace Webhook's pods" + description: "The maximum amount of memory that the Dynatrace Webhook's pods can use. Pod restarted if exceeded. Default: 128Mi" + default: "128Mi" + type: string + group: "Webhook Deployment Configuration" + + + #################### CSI Driver Deployment Configuration #################### + + - variable: csidriver.enabled + label: "Deploy the Dynatrace CSI Driver" + description: "Deploys the Dynatrace CSI Driver via a DaemonSet to enable Cloud Native FullStack. Default: false" + default: false + type: boolean + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.server.requests.cpu + label: "CPU resource requests settings for Dynatrace CSI Driver's server container" + description: "The minimum amount of CPU resources that the Dynatrace CSI Driver's server container should request. Affects scheduling. Default: 50m" + default: "50m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.server.requests.memory + label: "Memory resource requests settings for Dynatrace CSI Driver's server container" + description: "The minimum amount of memory that the Dynatrace CSI Driver's server container should request. Affects scheduling. Default: 100Mi" + default: "100Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.server.limits.cpu + label: "CPU resource limits settings for Dynatrace CSI Driver's server container" + description: "The maximum amount of CPU resources that the Dynatrace CSI Driver's server container can use. Default: 50m" + default: "50m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.server.limits.memory + label: "Memory resource limits settings for Dynatrace CSI Driver's server container" + description: "The maximum amount of memory that the Dynatrace CSI Driver's server container can use. Pod restarted if exceeded. Default: 100Mi" + default: "100Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.provisioner.requests.cpu + label: "CPU resource requests settings for Dynatrace CSI Driver's provisioner container" + description: "The minimum amount of CPU resources that the Dynatrace CSI Driver's provisioner container should request. Affects scheduling. Default: 300m" + default: "300m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.provisioner.requests.memory + label: "Memory resource requests settings for Dynatrace CSI Driver's provisioner container" + description: "The minimum amount of memory that the Dynatrace CSI Driver's provisioner container should request. Affects scheduling. Default: 100Mi" + default: "100Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.registrar.requests.cpu + label: "CPU resource requests settings for Dynatrace CSI Driver's registrar container" + description: "The minimum amount of CPU resources that the Dynatrace CSI Driver's registrar container should request. Affects scheduling. Default: 20m" + default: "20m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.registrar.requests.memory + label: "Memory resource requests settings for Dynatrace CSI Driver's registrar container" + description: "The minimum amount of memory that the Dynatrace CSI Driver's registrar container should request. Affects scheduling. Default: 30Mi" + default: "30Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.registrar.limits.cpu + label: "CPU resource limits settings for Dynatrace CSI Driver's registrar container" + description: "The maximum amount of CPU resources that the Dynatrace CSI Driver's registrar container can use. Default: 20m" + default: "20m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.registrar.limits.memory + label: "Memory resource limits settings for Dynatrace CSI Driver's registrar container" + description: "The maximum amount of memory that the Dynatrace CSI Driver's registrar container can use. Pod restarted if exceeded. Default: 30Mi" + default: "30Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.livenessprobe.requests.cpu + label: "CPU resource requests settings for Dynatrace CSI Driver's livenessprobe container" + description: "The minimum amount of CPU resources that the Dynatrace CSI Driver's livenessprobe container should request. Affects scheduling. Default: 20m" + default: "20m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.livenessprobe.requests.memory + label: "Memory resource requests settings for Dynatrace CSI Driver's livenessprobe container" + description: "The minimum amount of memory that the Dynatrace CSI Driver's livenessprobe container should request. Affects scheduling. Default: 30Mi" + default: "30Mi" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.livenessprobe.limits.cpu + label: "CPU resource limits settings for Dynatrace CSI Driver's livenessprobe container" + description: "The maximum amount of CPU resources that the Dynatrace CSI Driver's livenessprobe container can use. Default: 20m" + default: "20m" + type: string + group: "CSI Driver Deployment Configuration" + + - variable: csidriver.livenessprobe.limits.memory + label: "Memory resource limits settings for Dynatrace CSI Driver's livenessprobe container" + description: "The maximum amount of memory that the Dynatrace CSI Driver's livenessprobe container can use. Pod restarted if exceeded. Default: 30Mi" + default: "30Mi" + type: string + group: "CSI Driver Deployment Configuration" diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/clusterrole-activegate.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/clusterrole-activegate.yaml new file mode 100644 index 0000000000..9d41f7409c --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/clusterrole-activegate.yaml @@ -0,0 +1,47 @@ +{{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-activegate + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +rules: + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-activegate + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-activegate + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: dynatrace-activegate + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/serviceaccount-activegate.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/serviceaccount-activegate.yaml new file mode 100644 index 0000000000..93fe71a3f7 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/activegate/serviceaccount-activegate.yaml @@ -0,0 +1,20 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-activegate + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/crd/dynatrace-operator-crd.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/crd/dynatrace-operator-crd.yaml new file mode 100644 index 0000000000..ad4271f835 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/crd/dynatrace-operator-crd.yaml @@ -0,0 +1,5783 @@ +{{ if .Values.installCRD }} +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.3 + name: dynakubes.dynatrace.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: dynatrace-webhook + namespace: {{.Release.Namespace}} + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 + group: dynatrace.com + names: + categories: + - dynatrace + kind: DynaKube + listKind: DynaKubeList + plural: dynakubes + shortNames: + - dk + - dks + singular: dynakube + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.apiUrl + name: ApiUrl + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API + properties: + apiVersion: + 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 + type: string + kind: + 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 + type: string + metadata: + type: object + spec: + description: DynaKubeSpec defines the desired state of DynaKube + properties: + activeGate: + description: General configuration about ActiveGate instances. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ActiveGate pods + type: object + capabilities: + description: Activegate capabilities enabled (routing, kubernetes-monitoring, + metrics-ingest, dynatrace-api) + items: + type: string + type: array + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called 'customProperties' + properties: + value: + description: Custom properties value. + nullable: true + type: string + valueFrom: + description: Custom properties secret. + nullable: true + type: string + type: object + dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods + type: string + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: The ActiveGate container image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Adds additional labels for the ActiveGate pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + type: object + priorityClassName: + description: |- + If specified, indicates the pod's priority. Name must be defined by creating a PriorityClass object with that + name. If not specified the setting will be removed from the StatefulSet. + type: string + replicas: + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: Define resources requests and limits for single ActiveGate + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsSecretName: + description: |- + The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. + server.p12: certificate+key pair in pkcs12 format + password: passphrase to read server.p12 + type: string + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + apiUrl: + description: |- + Dynatrace apiUrl, including the /api path at the end. For SaaS, set YOUR_ENVIRONMENT_ID to your environment ID. For Managed, change the apiUrl address. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace.com/support/help/get-started/monitoring-environment/environment-id). + type: string + customPullSecret: + description: |- + Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. + To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret + (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#custompullsecret). + type: string + enableIstio: + description: |- + When enabled, and if Istio is installed on the Kubernetes environment, Dynatrace Operator will create the corresponding + VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. + Disabled by default. + type: boolean + kubernetesMonitoring: + description: Configuration for Kubernetes Monitoring + properties: + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called 'customProperties' + properties: + value: + description: Custom properties value. + nullable: true + type: string + valueFrom: + description: Custom properties secret. + nullable: true + type: string + type: object + enabled: + description: Enables Capability + type: boolean + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: The ActiveGate container image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Adds additional labels for the ActiveGate pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + type: object + replicas: + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: Define resources requests and limits for single ActiveGate + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#annotate). + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. + type: string + oneAgent: + description: |- + General configuration about OneAgent instances. + You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). + properties: + applicationMonitoring: + description: |- + dynatrace-webhook injects into application pods based on labeled namespaces. + Has an optional CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + useCSIDriver: + description: Set if you want to use the CSIDriver. Don't enable + it if you do not have access to Kubernetes nodes or if you + lack privileges. + type: boolean + version: + description: The OneAgent version to be used. + type: string + type: object + classicFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + Injection is performed via the same OneAgent DaemonSet. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used. + type: string + type: object + cloudNativeFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + dynatrace-webhook injects into application pods based on labeled namespaces. + Has a CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. + type: string + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used. + type: string + type: object + hostGroup: + description: Sets a host group for OneAgent. + type: string + hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + Note: resource.requests shows the values needed to run; resource.limits shows the maximum limits for the pod. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used. + type: string + type: object + type: object + proxy: + description: |- + Set custom proxy settings either directly or from a secret with the field proxy. + Note: Applies to Dynatrace Operator, ActiveGate, and OneAgents. + properties: + value: + description: Proxy URL. It has preference over ValueFrom. + nullable: true + type: string + valueFrom: + description: Secret containing proxy URL. + nullable: true + type: string + type: object + routing: + description: Configuration for Routing + properties: + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called 'customProperties' + properties: + value: + description: Custom properties value. + nullable: true + type: string + valueFrom: + description: Custom properties secret. + nullable: true + type: string + type: object + enabled: + description: Enables Capability + type: boolean + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: The ActiveGate container image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Adds additional labels for the ActiveGate pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes + type: object + replicas: + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: Define resources requests and limits for single ActiveGate + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints for the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + skipCertCheck: + description: |- + Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + Set to true if you want to skip certification validation checks. + type: boolean + tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. + type: string + trustedCAs: + description: |- + Adds custom RootCAs from a configmap. Put the certificate under certs within your configmap. + Note: Applies to Dynatrace Operator, OneAgent and ActiveGate. + type: string + required: + - apiUrl + type: object + status: + description: DynaKubeStatus defines the observed state of DynaKube + properties: + activeGate: + description: Observed state of ActiveGate + properties: + connectionInfoStatus: + description: Information about Active Gate's connections + properties: + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator + items: + type: string + type: array + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + codeModules: + description: Observed state of Code Modules + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dynatraceApi: + description: Observed state of Dynatrace API + properties: + lastTokenScopeRequest: + description: Time of the last token request + format: date-time + type: string + type: object + kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster + type: string + lastTokenProbeTimestamp: + description: LastTokenProbeTimestamp tracks when the last request + for the API token validity was sent + format: date-time + type: string + oneAgent: + description: Observed state of OneAgent + properties: + connectionInfoStatus: + description: Information about OneAgent's connections + properties: + communicationHosts: + description: List of communication hosts + items: + properties: + host: + description: Host domain + type: string + port: + description: Connection port + format: int32 + type: integer + protocol: + description: Connection protocol + type: string + type: object + type: array + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + healthcheck: + description: Commands used for OneAgent's readiness probe + type: object + x-kubernetes-preserve-unknown-fields: true + imageID: + description: Image ID + type: string + instances: + additionalProperties: + properties: + ipAddress: + description: IP address of the pod + type: string + podName: + description: Name of the OneAgent pod + type: string + type: object + description: List of deployed OneAgent instances + type: object + lastInstanceStatusUpdate: + description: Time of the last instance status update + format: date-time + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.apiUrl + name: ApiUrl + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: DynaKube is the Schema for the DynaKube API + properties: + apiVersion: + 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 + type: string + kind: + 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 + type: string + metadata: + type: object + spec: + description: DynaKubeSpec defines the desired state of DynaKube + properties: + activeGate: + description: General configuration about ActiveGate instances. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the ActiveGate pods + type: object + capabilities: + description: "Defines the ActiveGate pod capabilities\nPossible + values:\n\t- `routing` enables OneAgent routing.\n\t- `kubernetes-monitoring` + enables Kubernetes API monitoring.\n\t- `metrics-ingest` opens + the metrics ingest endpoint on the DynaKube ActiveGate and redirects + all pods to it.\n\t- `dynatrace-api` enables calling the Dynatrace + API via ActiveGate." + items: + type: string + type: array + customProperties: + description: |- + Add a custom properties file by providing it as a value or reference it from a secret + If referenced from a secret, make sure the key is called `customProperties` + properties: + value: + description: Custom properties value. + nullable: true + type: string + valueFrom: + description: Custom properties secret. + nullable: true + type: string + type: object + dnsPolicy: + description: Sets DNS Policy for the ActiveGate pods + type: string + env: + description: List of environment variables to set for the ActiveGate + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must be a + C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the + specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the + exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + group: + description: Set activation group for ActiveGate + type: string + image: + description: Use a custom ActiveGate image. Defaults to the latest + ActiveGate image provided by the registry on the tenant + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for ActiveGate pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes ActiveGate will be deployed. + type: object + priorityClassName: + description: |- + Assign a priority class to the ActiveGate pods. By default, no class is set. + For details, see Pod Priority and Preemption. (https://dt-url.net/n8437bl) + type: string + replicas: + default: 1 + description: Amount of replicas for your ActiveGates + format: int32 + type: integer + resources: + description: |- + Resource settings for ActiveGate container. + Consumption of the ActiveGate heavily depends on the workload to monitor. Adjust values accordingly. + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + tlsSecretName: + description: |- + The name of a secret containing ActiveGate TLS cert+key and password. If not set, self-signed certificate is used. + `server.p12`: certificate+key pair in pkcs12 format + `password`: passphrase to read server.p12 + type: string + tolerations: + description: Set tolerations for the ActiveGate pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Adds TopologySpreadConstraints to the ActiveGate + pods + items: + description: TopologySpreadConstraint specifies how to spread + matching pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + type: object + apiUrl: + description: |- + Dynatrace `apiUrl`, including the `/api` path at the end. + - For SaaS, set `YOUR_ENVIRONMENT_ID` to your environment ID. + - For Managed, change the `apiUrl` address. + For instructions on how to determine the environment ID and how to configure the apiUrl address, see Environment ID (https://www.dynatrace.com/support/help/get-started/monitoring-environment/environment-id). + type: string + customPullSecret: + description: |- + Defines a custom pull secret in case you use a private registry when pulling images from the Dynatrace environment. + To define a custom pull secret and learn about the expected behavior, see Configure customPullSecret + (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#custompullsecret). + type: string + dynatraceApiRequestThreshold: + default: 15 + description: Minimum minutes between Dynatrace API requests. + type: integer + enableIstio: + description: |- + When enabled, and if Istio is installed in the Kubernetes environment, Dynatrace Operator will create the corresponding VirtualService and ServiceEntry objects to allow access to the Dynatrace Cluster from the OneAgent or ActiveGate. + Disabled by default. + type: boolean + metadataEnrichment: + description: Configuration for Metadata Enrichment. + properties: + enabled: + default: false + description: Enables MetadataEnrichment, `false` by default. + type: boolean + namespaceSelector: + description: The namespaces where you want Dynatrace Operator + to inject enrichment. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - enabled + type: object + networkZone: + description: Sets a network zone for the OneAgent and ActiveGate pods. + type: string + oneAgent: + description: |- + General configuration about OneAgent instances. + You can't enable more than one module (classicFullStack, cloudNativeFullStack, hostMonitoring, or applicationMonitoring). + properties: + applicationMonitoring: + description: |- + dynatrace-webhook injects into application pods based on labeled namespaces. + Has an optional CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#annotate). + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + useCSIDriver: + default: false + description: Set if you want to use the CSIDriver. Don't enable + it if you do not have access to Kubernetes nodes or if you + lack privileges. + type: boolean + version: + description: The OneAgent version to be used. + type: string + type: object + classicFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + Injection is performed via the same OneAgent DaemonSet. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + default: true + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + - `resource.requests` shows the values needed to run + - `resource.limits` shows the maximum limits for the pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. This setting doesn't affect + the OneAgent version used for application monitoring. + type: string + type: object + cloudNativeFullStack: + description: |- + Has a single OneAgent per node via DaemonSet. + dynatrace-webhook injects into application pods based on labeled namespaces. + Has a CSI driver per node via DaemonSet to provide binaries to pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + default: true + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + codeModulesImage: + description: The OneAgent image that is used to inject into + Pods. + type: string + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + initResources: + description: |- + Define resources requests and limits for the initContainer. For details, see Managing resources for containers + (https://kubernetes.io/docs/concepts/configuration/manage-resources-containers). + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + namespaceSelector: + description: |- + Applicable only for applicationMonitoring or cloudNativeFullStack configuration types. The namespaces where you want Dynatrace Operator to inject. + For more information, see Configure monitoring for namespaces and pods (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring/dto-config-options-k8s#annotate). + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + - `resource.requests` shows the values needed to run + - `resource.limits` shows the maximum limits for the pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. This setting doesn't affect + the OneAgent version used for application monitoring. + type: string + type: object + hostGroup: + description: |- + Specify the name of the group to which you want to assign the host. + This method is preferred over the now obsolete `--set-host-group` argument. + If both settings are used, this field takes precedence over the `--set-host-group` argument. + type: string + hostMonitoring: + description: |- + Has a single OneAgent per node via DaemonSet. + Doesn't inject into application pods. + nullable: true + properties: + annotations: + additionalProperties: + type: string + description: Add custom OneAgent annotations. + type: object + args: + description: |- + Set additional arguments to the OneAgent installer. + For available options, see Linux custom installation (https://www.dynatrace.com/support/help/setup-and-configuration/dynatrace-oneagent/installation-and-operation/linux/installation/customize-oneagent-installation-on-linux). + For the list of limitations, see Limitations (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/docker/set-up-dynatrace-oneagent-as-docker-container#limitations). + items: + type: string + type: array + x-kubernetes-list-type: set + autoUpdate: + default: true + description: |- + Disables automatic restarts of OneAgent pods in case a new version is available (https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/get-started-with-kubernetes-monitoring#disable-auto). + Enabled by default. + type: boolean + dnsPolicy: + description: Set the DNS Policy for OneAgent pods. For details, + see Pods DNS Policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy). + type: string + env: + description: Set additional environment variables for the + OneAgent pods. + items: + description: EnvVar represents an environment variable present + in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or + its key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's + namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its + key must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + image: + description: Use a custom OneAgent Docker image. Defaults + to the image from the Dynatrace cluster. + type: string + labels: + additionalProperties: + type: string + description: Your defined labels for OneAgent pods in order + to structure workloads as desired. + type: object + nodeSelector: + additionalProperties: + type: string + description: Specify the node selector that controls on which + nodes OneAgent will be deployed. + type: object + oneAgentResources: + description: |- + Resource settings for OneAgent container. Consumption of the OneAgent heavily depends on the workload to monitor. You can use the default settings in the CR. + - `resource.requests` shows the values needed to run + - `resource.limits` shows the maximum limits for the pod + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + priorityClassName: + description: |- + Assign a priority class to the OneAgent pods. By default, no class is set. + For details, see Pod Priority and Preemption (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/). + type: string + secCompProfile: + description: The SecComp Profile that will be configured in + order to run in secure computing mode. + type: string + tolerations: + description: Tolerations to include with the OneAgent DaemonSet. + For details, see Taints and Tolerations (https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + version: + description: The OneAgent version to be used for OneAgents + running in the dedicated pod. This setting doesn't affect + the OneAgent version used for application monitoring. + type: string + type: object + type: object + proxy: + description: |- + Set custom proxy settings either directly or from a secret with the field `proxy`. + Applies to Dynatrace Operator, ActiveGate, and OneAgents. + properties: + value: + description: Proxy URL. It has preference over ValueFrom. + nullable: true + type: string + valueFrom: + description: Secret containing proxy URL. + nullable: true + type: string + type: object + skipCertCheck: + description: |- + Disable certificate check for the connection between Dynatrace Operator and the Dynatrace Cluster. + Set to `true` if you want to skip certification validation checks. + type: boolean + tokens: + description: Name of the secret holding the tokens used for connecting + to Dynatrace. + type: string + trustedCAs: + description: |- + Adds custom RootCAs from a configmap. + The key to the data must be `certs`. + This applies to both the Dynatrace Operator and the OneAgent. Doesn't apply to ActiveGate. + type: string + required: + - apiUrl + type: object + status: + description: DynaKubeStatus defines the observed state of DynaKube + properties: + activeGate: + description: Observed state of ActiveGate + properties: + connectionInfoStatus: + description: Information about Active Gate's connections + properties: + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + serviceIPs: + description: The ClusterIPs set by Kubernetes on the ActiveGate + Service created by the Operator + items: + type: string + type: array + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + codeModules: + description: Observed state of Code Modules + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + dynatraceApi: + description: Observed state of Dynatrace API + properties: + lastTokenScopeRequest: + description: Time of the last token request + format: date-time + type: string + type: object + kubeSystemUUID: + description: KubeSystemUUID contains the UUID of the current Kubernetes + cluster + type: string + kubernetesClusterMEID: + description: KubernetesClusterMEID contains the ID of the monitored + entity that points to the Kubernetes cluster + type: string + kubernetesClusterName: + description: KubernetesClusterName contains the display name (also + know as label) of the monitored entity that points to the Kubernetes + cluster + type: string + metadataEnrichment: + description: Observed state of Metadata-Enrichment + properties: + rules: + items: + properties: + enabled: + type: boolean + source: + type: string + target: + type: string + type: + type: string + type: object + type: array + type: object + oneAgent: + description: Observed state of OneAgent + properties: + connectionInfoStatus: + description: Information about OneAgent's connections + properties: + communicationHosts: + description: List of communication hosts + items: + properties: + host: + description: Host domain + type: string + port: + description: Connection port + format: int32 + type: integer + protocol: + description: Connection protocol + type: string + type: object + type: array + endpoints: + description: Available connection endpoints + type: string + lastRequest: + description: Time of the last connection request + format: date-time + type: string + tenantUUID: + description: UUID of the tenant, received from the tenant + type: string + type: object + healthcheck: + description: Commands used for OneAgent's readiness probe + type: object + x-kubernetes-preserve-unknown-fields: true + imageID: + description: Image ID + type: string + instances: + additionalProperties: + properties: + ipAddress: + description: IP address of the pod + type: string + podName: + description: Name of the OneAgent pod + type: string + type: object + description: List of deployed OneAgent instances + type: object + lastInstanceStatusUpdate: + description: Time of the last instance status update + format: date-time + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: UpdatedTimestamp indicates when the instance was last + updated + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.3 + name: edgeconnects.dynatrace.com +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: dynatrace-webhook + namespace: {{.Release.Namespace}} + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 + group: dynatrace.com + names: + categories: + - dynatrace + kind: EdgeConnect + listKind: EdgeConnectList + plural: edgeconnects + shortNames: + - ec + - ecs + singular: edgeconnect + preserveUnknownFields: false + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.apiServer + name: ApiServer + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API + properties: + apiVersion: + 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 + type: string + kind: + 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 + type: string + metadata: + type: object + spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the EdgeConnect pods + type: object + apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID + type: string + autoUpdate: + default: true + description: 'Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default value is: true)' + type: boolean + caCertsRef: + description: Adds custom root certificate from a configmap. Put the + certificate under certs within your configmap. + type: string + customPullSecret: + description: Pull secret for your private registry + type: string + env: + description: Adds additional environment variables to the EdgeConnect + pods + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. + items: + type: string + type: array + hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts + example: internal.example.org,*.dev.example.org + type: string + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom EdgeConnect image repository + example: docker.io/dynatrace/edgeconnect + type: string + tag: + description: Indicates version of the EdgeConnect image to use + type: string + type: object + kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows + properties: + enabled: + description: Enables Kubernetes Automation for Workflows + type: boolean + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels to the EdgeConnect pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods + type: object + oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. + properties: + clientSecret: + description: Name of the secret that holds oauth clientId/secret + type: string + endpoint: + description: Token endpoint URL of Dynatrace SSO + type: string + provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using the credentials + provided. Requires more scopes than default behavior. + type: boolean + resource: + description: URN identifying your account. You get the URN when + creating the OAuth client + type: string + required: + - clientSecret + - endpoint + - resource + type: object + proxy: + description: General configurations for proxy settings. + properties: + authRef: + description: |- + Secret name which contains the username and password used for authentication with the proxy, using the + "Basic" HTTP authentication scheme. + type: string + host: + description: Server address (hostname or IP address) of the proxy. + type: string + noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. It specifies a string that contains comma-separated values + specifying hosts that should be excluded from proxying. + type: string + port: + description: Port of the proxy. + format: int32 + type: integer + type: object + replicas: + default: 1 + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' + format: int32 + type: integer + resources: + description: Defines resources requests and limits for single pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + serviceAccountName: + default: dynatrace-edgeconnect + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API + type: string + tolerations: + description: Sets tolerations for the EdgeConnect pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + required: + - apiServer + - oauth + type: object + status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. + properties: + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + kubeSystemUID: + description: kube-system namespace uid + type: string + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: Indicates when the resource was last updated + format: date-time + type: string + version: + description: Version used for the Edgeconnect image + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.apiServer + name: ApiServer + type: string + - jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: EdgeConnect is the Schema for the EdgeConnect API + properties: + apiVersion: + 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 + type: string + kind: + 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 + type: string + metadata: + type: object + spec: + description: EdgeConnectSpec defines the desired state of EdgeConnect. + properties: + annotations: + additionalProperties: + type: string + description: Adds additional annotations to the EdgeConnect pods + type: object + apiServer: + description: Location of the Dynatrace API to connect to, including + your specific environment UUID + type: string + autoUpdate: + default: true + description: 'Enables automatic restarts of EdgeConnect pods in case + a new version is available (the default value is: true)' + type: boolean + caCertsRef: + description: Adds custom root certificate from a configmap. Put the + certificate under certs within your configmap. + type: string + customPullSecret: + description: Pull secret for your private registry + type: string + env: + description: Adds additional environment variables to the EdgeConnect + pods + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: |- + Variable references $(VAR_NAME) are expanded + using the previously defined environment variables in the container and + any service environment variables. If a variable cannot be resolved, + the reference in the input string will be unchanged. Double $$ are reduced + to a single $, which allows for escaping the $(VAR_NAME) syntax: i.e. + "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". + Escaped references will never be expanded, regardless of whether the variable + exists or not. + Defaults to "". + type: string + valueFrom: + description: Source for the environment variable's value. Cannot + be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the ConfigMap or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + description: |- + Selects a field of the pod: supports metadata.name, metadata.namespace, `metadata.labels['']`, `metadata.annotations['']`, + spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP, status.podIPs. + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + description: |- + Selects a resource of the container: only resources limits and requests + (limits.cpu, limits.memory, limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage) are currently supported. + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of the exposed + resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + hostPatterns: + description: Host patterns to be set in the tenant, only considered + when provisioning is enabled. + items: + type: string + type: array + hostRestrictions: + description: Restrict outgoing HTTP requests to your internal resources + to specified hosts + example: internal.example.org,*.dev.example.org + items: + type: string + type: array + imageRef: + description: Overrides the default image + properties: + repository: + description: Custom EdgeConnect image repository + example: docker.io/dynatrace/edgeconnect + type: string + tag: + description: Indicates version of the EdgeConnect image to use + type: string + type: object + kubernetesAutomation: + description: KubernetesAutomation enables Kubernetes Automation for + Workflows + properties: + enabled: + description: Enables Kubernetes Automation for Workflows + type: boolean + type: object + labels: + additionalProperties: + type: string + description: Adds additional labels to the EdgeConnect pods + type: object + nodeSelector: + additionalProperties: + type: string + description: Node selector to control the selection of nodes for the + EdgeConnect pods + type: object + oauth: + description: EdgeConnect uses the OAuth client to authenticate itself + with the Dynatrace platform. + properties: + clientSecret: + description: Name of the secret that holds oauth clientId/secret + type: string + endpoint: + description: Token endpoint URL of Dynatrace SSO + type: string + provisioner: + description: Determines if the operator will create the EdgeConnect + and light OAuth client on the cluster using the credentials + provided. Requires more scopes than default behavior. + type: boolean + resource: + description: URN identifying your account. You get the URN when + creating the OAuth client + type: string + required: + - clientSecret + - endpoint + - resource + type: object + proxy: + description: General configurations for proxy settings. + properties: + authRef: + description: |- + Secret name which contains the username and password used for authentication with the proxy, using the + "Basic" HTTP authentication scheme. + type: string + host: + description: Server address (hostname or IP address) of the proxy. + type: string + noProxy: + description: |- + NoProxy represents the NO_PROXY or no_proxy environment + variable. It specifies a string that contains comma-separated values + specifying hosts that should be excluded from proxying. + type: string + port: + description: Port of the proxy. + format: int32 + type: integer + type: object + replicas: + default: 1 + description: 'Amount of replicas for your EdgeConnect (the default + value is: 1)' + format: int32 + type: integer + resources: + description: Defines resources requests and limits for single pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This is an alpha field and requires enabling the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + serviceAccountName: + default: dynatrace-edgeconnect + description: ServiceAccountName that allows EdgeConnect to access + the Kubernetes API + type: string + tolerations: + description: Sets tolerations for the EdgeConnect pods + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + topologySpreadConstraints: + description: Sets topology spread constraints for the EdgeConnect + pods + items: + description: TopologySpreadConstraint specifies how to spread matching + pods among the given topology. + properties: + labelSelector: + description: |- + LabelSelector is used to find matching pods. + Pods that match this label selector are counted to determine the number of pods + in their corresponding topology domain. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select the pods over which + spreading will be calculated. The keys are used to lookup values from the + incoming pod labels, those key-value labels are ANDed with labelSelector + to select the group of existing pods over which spreading will be calculated + for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. + MatchLabelKeys cannot be set when LabelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + description: |- + MaxSkew describes the degree to which pods may be unevenly distributed. + When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference + between the number of matching pods in the target topology and the global minimum. + The global minimum is the minimum number of matching pods in an eligible domain + or zero if the number of eligible domains is less than MinDomains. + format: int32 + type: integer + minDomains: + description: |- + MinDomains indicates a minimum number of eligible domains. + When the number of eligible domains with matching topology keys is less than minDomains, + Pod Topology Spread treats "global minimum" as 0, and then the calculation of Skew is performed. + And when the number of eligible domains with matching topology keys equals or greater than minDomains, + this value has no effect on scheduling. + format: int32 + type: integer + nodeAffinityPolicy: + description: |- + NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector + when calculating pod topology spread skew. Options are: + - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. + - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. + + If this value is nil, the behavior is equivalent to the Honor policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + nodeTaintsPolicy: + description: |- + NodeTaintsPolicy indicates how we will treat node taints when calculating + pod topology spread skew. Options are: + - Honor: nodes without taints, along with tainted nodes for which the incoming pod + has a toleration, are included. + - Ignore: node taints are ignored. All nodes are included. + + If this value is nil, the behavior is equivalent to the Ignore policy. + This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. + type: string + topologyKey: + description: |- + TopologyKey is the key of node labels. Nodes that have a label with this key + and identical values are considered to be in the same topology. + We consider each as a "bucket", and try to put balanced number + of pods into each bucket. + We define a domain as a particular instance of a topology. + Also, we define an eligible domain as a domain whose nodes meet the requirements of + nodeAffinityPolicy and nodeTaintsPolicy. + e.g. If TopologyKey is "kubernetes. + type: string + whenUnsatisfiable: + description: |- + WhenUnsatisfiable indicates how to deal with a pod if it doesn't satisfy + the spread constraint. + - DoNotSchedule (default) tells the scheduler not to schedule it. + - ScheduleAnyway tells the scheduler to schedule the pod in any location, + but giving higher precedence to topologies that would help reduce the + skew. + A constraint is considered "Unsatisfiable" for an incoming pod + if and only if every possible node assignment for that pod would violate + "MaxSkew" on some topology. + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + required: + - apiServer + - oauth + type: object + status: + description: EdgeConnectStatus defines the observed state of EdgeConnect. + properties: + conditions: + description: Conditions includes status about the current state of + the instance + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + kubeSystemUID: + description: kube-system namespace uid + type: string + phase: + description: Defines the current state (Running, Updating, Error, + ...) + type: string + updatedTimestamp: + description: Indicates when the resource was last updated + format: date-time + type: string + version: + description: Version used for the Edgeconnect image + properties: + imageID: + description: Image ID + type: string + lastProbeTimestamp: + description: Indicates when the last check for a new version was + performed + format: date-time + type: string + source: + description: Source of the image (tenant-registry, public-registry, + ...) + type: string + type: + description: Image type + type: string + version: + description: Image version + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/clusterrole-csi.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/clusterrole-csi.yaml new file mode 100644 index 0000000000..213bd73b00 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/clusterrole-csi.yaml @@ -0,0 +1,47 @@ +{{ if eq (include "dynatrace-operator.needCSI" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-oneagent-csi-driver + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +rules: + {{- if (eq (include "dynatrace-operator.platform" .) "openshift") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-oneagent-csi-driver + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: dynatrace-oneagent-csi-driver + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/csidriver.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/csidriver.yaml new file mode 100644 index 0000000000..dbef0127a3 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/csidriver.yaml @@ -0,0 +1,29 @@ +{{ if eq (include "dynatrace-operator.needCSI" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: storage.k8s.io/v1 +kind: CSIDriver +metadata: + name: csi.oneagent.dynatrace.com + labels: + {{- if eq (include "dynatrace-operator.platform" .) "openshift" }} + security.openshift.io/csi-ephemeral-volume-profile: "restricted" + {{- end }} + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +spec: + attachRequired: false + podInfoOnMount: true + volumeLifecycleModes: + - Ephemeral +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/daemonset.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/daemonset.yaml new file mode 100644 index 0000000000..c24305ed49 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/daemonset.yaml @@ -0,0 +1,280 @@ +{{ if eq (include "dynatrace-operator.needCSI" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: apps/v1 +kind: DaemonSet +metadata: + annotations: + {{- if .Values.csidriver.annotations }} + {{- toYaml .Values.csidriver.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} + {{- if .Values.csidriver.labels }} + {{- toYaml .Values.csidriver.labels | nindent 4 }} + {{- end}} + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} +spec: + revisionHistoryLimit: 10 + selector: + matchLabels: + {{- include "dynatrace-operator.csiSelectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + dynatrace.com/inject: "false" + kubectl.kubernetes.io/default-container: provisioner + cluster-autoscaler.kubernetes.io/enable-ds-eviction: "false" + {{- if and (eq (default false .Values.apparmor) true) (ne (include "dynatrace-operator.platform" .) "openshift") }} + container.apparmor.security.beta.kubernetes.io/csi-init: runtime/default + container.apparmor.security.beta.kubernetes.io/server: runtime/default + container.apparmor.security.beta.kubernetes.io/provisioner: runtime/default + container.apparmor.security.beta.kubernetes.io/registrar: runtime/default + container.apparmor.security.beta.kubernetes.io/liveness-probe: runtime/default + {{- end}} + {{- if .Values.csidriver.annotations }} + {{- toYaml .Values.csidriver.annotations | nindent 8 }} + {{- end }} + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 8 }} + {{- include "dynatrace-operator.csiSelectorLabels" . | nindent 8 }} + {{- if .Values.csidriver.labels }} + {{- toYaml .Values.csidriver.labels | nindent 8 }} + {{- end }} + spec: + initContainers: + - name: csi-init + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + args: + - csi-init + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + resources: + {{- if .Values.csidriver.csiInit.resources }} + {{- toYaml .Values.csidriver.csiInit.resources | nindent 10 }} + {{- end }} + securityContext: + {{- toYaml .Values.csidriver.csiInit.securityContext| nindent 10 }} + volumeMounts: + - mountPath: /data + name: data-dir + containers: + # Used to receive/execute gRPC requests (NodePublishVolume/NodeUnpublishVolume) from kubelet to mount/unmount volumes for a pod + # - Needs access to the csi socket, needs to read/write to it, needs root permissions to do so. + # - Needs access to the filesystem of pods on the node, and mount stuff to it,needs to read/write to it, needs root permissions to do so + # - Needs access to a dedicated folder on the node to persist data, needs to read/write to it. + - name: server + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + args: + - csi-server + - --endpoint=unix://csi/csi.sock + - --node-id=$(KUBE_NODE_NAME) + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: KUBE_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: healthz + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + ports: + - containerPort: 9808 + name: healthz + - containerPort: 8080 + name: metrics + resources: + {{- if .Values.csidriver.server.resources }} + {{- toYaml .Values.csidriver.server.resources | nindent 10 }} + {{- end }} + securityContext: + {{- toYaml .Values.csidriver.server.securityContext | nindent 10 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /csi + name: plugin-dir + - mountPath: {{ include "dynatrace-operator.CSIMountPointDir" . }} + mountPropagation: Bidirectional + name: mountpoint-dir + - mountPath: /data + name: data-dir + mountPropagation: Bidirectional + - name: tmp-dir + mountPath: /tmp + - name: provisioner + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + args: + - csi-provisioner + - --health-probe-bind-address=:10090 + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + {{- if .Values.csidriver.maxUnmountedVolumeAge }} + - name: MAX_UNMOUNTED_VOLUME_AGE + value: "{{ .Values.csidriver.maxUnmountedVolumeAge}}" + {{- end }} + {{- include "dynatrace-operator.startupProbe" . | nindent 8 }} + livenessProbe: + failureThreshold: 3 + httpGet: + path: /livez + port: livez + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 1 + ports: + - name: livez + containerPort: 10090 + - name: metrics + containerPort: 8090 + resources: + {{- if .Values.csidriver.provisioner.resources }} + {{- toYaml .Values.csidriver.provisioner.resources | nindent 10 }} + {{- end }} + securityContext: + {{- toYaml .Values.csidriver.provisioner.securityContext | nindent 10 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /data + name: data-dir + mountPropagation: Bidirectional + - mountPath: /tmp + name: tmp-dir + + # Used to make a gRPC request (GetPluginInfo()) to the driver to get driver name and driver contain + # - Needs access to the csi socket, needs to read/write to it, needs root permissions to do so. + # Used for registering the driver with kubelet + # - Needs access to the registration socket, needs to read/write to it, needs root permissions to do so. + - name: registrar + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + env: + - name: DRIVER_REG_SOCK_PATH + value: {{ include "dynatrace-operator.CSISocketPath" . }} + args: + - --csi-address=/csi/csi.sock + - --kubelet-registration-path=$(DRIVER_REG_SOCK_PATH) + command: + - csi-node-driver-registrar + resources: + {{- if .Values.csidriver.registrar.resources }} + {{- toYaml .Values.csidriver.registrar.resources | nindent 10 }} + {{- end }} + securityContext: + {{- toYaml .Values.csidriver.registrar.securityContext | nindent 10 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /csi + name: plugin-dir + - mountPath: /registration + name: registration-dir + - mountPath: {{ include "dynatrace-operator.CSIPluginDir" . }} + name: lockfile-dir + # Used to make a gRPC request (Probe()) to the driver to check if its running + # - Needs access to the csi socket, needs to read/write to it, needs root permissions to do so. + - name: liveness-probe + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + args: + - --csi-address=/csi/csi.sock + - --health-port=9808 + command: + - livenessprobe + resources: + {{- if .Values.csidriver.livenessprobe.resources }} + {{- toYaml .Values.csidriver.livenessprobe.resources | nindent 10 }} + {{- end }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + securityContext: + {{- toYaml .Values.csidriver.livenessprobe.securityContext| nindent 10 }} + volumeMounts: + - mountPath: /csi + name: plugin-dir + dnsPolicy: ClusterFirst + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccountName: dynatrace-oneagent-csi-driver + terminationGracePeriodSeconds: 30 + priorityClassName: {{ include "dynatrace-operator.CSIPriorityClassName" . }} + volumes: + # This volume is where the registrar registers the plugin with kubelet + - name: registration-dir + hostPath: + path: {{ include "dynatrace-operator.CSIRegistrationDir" . }} + type: Directory + # This volume is where the socket for kubelet->driver communication is done + - name: plugin-dir + hostPath: + path: {{ include "dynatrace-operator.CSIPluginDir" . }} + type: DirectoryOrCreate + - name: data-dir + hostPath: + path: {{ include "dynatrace-operator.CSIDataDir" . }} + type: DirectoryOrCreate + # This volume is where the driver mounts volumes + - name: mountpoint-dir + hostPath: + path: {{ include "dynatrace-operator.CSIMountPointDir" . }} + type: DirectoryOrCreate + # Used by the registrar to create its lockfile + - name: lockfile-dir + emptyDir: {} + # A volume for the driver to write temporary files to + - name: tmp-dir + emptyDir: {} + {{- if .Values.customPullSecret }} + imagePullSecrets: + - name: {{ .Values.customPullSecret }} + {{- end }} + {{- if .Values.csidriver.nodeSelector }} + nodeSelector: {{- toYaml .Values.csidriver.nodeSelector | nindent 8 }} + {{- end }} + {{- include "dynatrace-operator.nodeAffinity" . | nindent 6 }} + tolerations: + {{- if .Values.csidriver.tolerations }} + {{- toYaml .Values.csidriver.tolerations | nindent 8 }} + {{- end }} + {{- include "dynatrace-operator.defaultTolerations" . | nindent 8 }} + - key: ToBeDeletedByClusterAutoscaler + operator: Exists + effect: NoSchedule + updateStrategy: + {{- toYaml .Values.csidriver.updateStrategy | nindent 4 }} +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/priority-class.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/priority-class.yaml new file mode 100644 index 0000000000..c668ac4d6b --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/priority-class.yaml @@ -0,0 +1,23 @@ +{{ if (eq (include "dynatrace-operator.needPriorityClass" .) "true") }} + +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kind: PriorityClass +apiVersion: scheduling.k8s.io/v1 +metadata: + name: dynatrace-high-priority +value: {{ default 1000000 (int (.Values.csidriver).priorityClassValue) }} +globalDefault: false +description: "This priority class is used for Dynatrace Components in order to make sure they are not evicted in favor of other pods" +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/role-csi.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/role-csi.yaml new file mode 100644 index 0000000000..654ab04e13 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/role-csi.yaml @@ -0,0 +1,70 @@ +{{ if eq (include "dynatrace-operator.needCSI" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +rules: + - apiGroups: + - dynatrace.com + resources: + - dynakubes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: dynatrace-oneagent-csi-driver + apiGroup: rbac.authorization.k8s.io +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/serviceaccount-csi.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/serviceaccount-csi.yaml new file mode 100644 index 0000000000..7485d26440 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/csi/serviceaccount-csi.yaml @@ -0,0 +1,22 @@ +{{ if eq (include "dynatrace-operator.needCSI" .) "true" }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-oneagent-csi-driver + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.csiLabels" . | nindent 4 }} +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/edge-connect/serviceaccount-operator.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/edge-connect/serviceaccount-operator.yaml new file mode 100644 index 0000000000..45f1d9ac6f --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/edge-connect/serviceaccount-operator.yaml @@ -0,0 +1,20 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-edgeconnect + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml new file mode 100644 index 0000000000..fab70e8777 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/clusterrole-kubernetes-monitoring.yaml @@ -0,0 +1,114 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-kubernetes-monitoring + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - nodes + - pods + - namespaces + - replicationcontrollers + - events + - resourcequotas + - pods/proxy + - nodes/proxy + - nodes/metrics + - services + verbs: + - list + - watch + - get + - apiGroups: + - batch + resources: + - jobs + - cronjobs + verbs: + - list + - watch + - get + - apiGroups: + - apps + resources: + - deployments + - replicasets + - statefulsets + - daemonsets + verbs: + - list + - watch + - get + - apiGroups: + - apps.openshift.io + resources: + - deploymentconfigs + verbs: + - list + - watch + - get + - apiGroups: + - config.openshift.io + resources: + - clusterversions + verbs: + - list + - watch + - get + - apiGroups: + - dynatrace.com + resources: + - dynakubes + verbs: + - list + - watch + - get + - nonResourceURLs: + - /metrics + - /version + - /readyz + - /livez + verbs: + - get + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-kubernetes-monitoring + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dynatrace-kubernetes-monitoring +subjects: + - kind: ServiceAccount + name: dynatrace-kubernetes-monitoring + namespace: {{ .Release.Namespace }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml new file mode 100644 index 0000000000..bd1e9c4431 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/kubernetes-monitoring/serviceaccount-kubernetes-monitoring.yaml @@ -0,0 +1,20 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-kubernetes-monitoring + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.activegateLabels" . | nindent 4 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/clusterrole-oneagent.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/clusterrole-oneagent.yaml new file mode 100644 index 0000000000..3e0616725b --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/clusterrole-oneagent.yaml @@ -0,0 +1,45 @@ +{{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-dynakube-oneagent + labels: + {{- include "dynatrace-operator.oneagentLabels" . | nindent 4 }} +rules: + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-dynakube-oneagent + labels: + {{- include "dynatrace-operator.oneagentLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-dynakube-oneagent + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dynatrace-dynakube-oneagent +{{ end }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/serviceaccount-oneagent.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/serviceaccount-oneagent.yaml new file mode 100644 index 0000000000..18d3a9ae26 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/oneagent/serviceaccount-oneagent.yaml @@ -0,0 +1,21 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-dynakube-oneagent + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.oneagentLabels" . | nindent 4 }} +automountServiceAccountToken: false diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/clusterrole-operator.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/clusterrole-operator.yaml new file mode 100644 index 0000000000..a9098dd3df --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/clusterrole-operator.yaml @@ -0,0 +1,109 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-operator + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - dynatrace-dynakube-config + - dynatrace-metadata-enrichment-endpoint + verbs: + - get + - update + - delete + - list + - apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + resourceNames: + - dynatrace-webhook + verbs: + - get + - update + - apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + resourceNames: + - dynatrace-webhook + verbs: + - get + - update + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + resourceNames: + - dynakubes.dynatrace.com + - edgeconnects.dynatrace.com + verbs: + - get + - update + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-operator + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-operator + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: dynatrace-operator + apiGroup: rbac.authorization.k8s.io diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/deployment-operator.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/deployment-operator.yaml new file mode 100644 index 0000000000..10143d58e0 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/deployment-operator.yaml @@ -0,0 +1,111 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dynatrace-operator + namespace: {{ .Release.Namespace }} + annotations: + {{- if .Values.operator.annotations }} + {{- toYaml .Values.operator.annotations | nindent 4 }} + {{- end }} + labels: + dynatrace.com/install-source: {{ include "dynatrace-operator.installSource" . }} + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} + {{- if .Values.operator.labels }} + {{- toYaml .Values.operator.labels | nindent 4 }} + {{- end }} +spec: + replicas: 1 + revisionHistoryLimit: 1 + selector: + matchLabels: + {{- include "dynatrace-operator.operatorSelectorLabels" . | nindent 6 }} + strategy: + type: RollingUpdate + template: + metadata: + annotations: + dynatrace.com/inject: "false" + {{- if (.Values.operator).apparmor}} + container.apparmor.security.beta.kubernetes.io/operator: runtime/default + {{- end }} + {{- if .Values.operator.annotations }} + {{- toYaml .Values.operator.annotations | nindent 8 }} + {{- end }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 8 }} + {{- include "dynatrace-operator.operatorSelectorLabels" . | nindent 8 }} + {{- if .Values.operator.labels }} + {{- toYaml .Values.operator.labels | nindent 8 }} + {{- end }} + spec: + containers: + - name: operator + args: + - operator + # Replace this with the built image name + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + ports: + - containerPort: 10080 + name: livez + - containerPort: 8080 + name: metrics + resources: + requests: + {{- toYaml (.Values.operator).requests | nindent 14 }} + limits: + {{- toYaml (.Values.operator).limits | nindent 14 }} + volumeMounts: + - name: tmp-cert-dir + mountPath: /tmp/dynatrace-operator + livenessProbe: + httpGet: + path: /livez + port: livez + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 10 + {{- include "dynatrace-operator.startupProbe" . | nindent 10 }} + securityContext: + {{- toYaml .Values.operator.securityContext | nindent 12 }} + {{- include "dynatrace-operator.nodeAffinity" . | nindent 6 }} + volumes: + - emptyDir: { } + name: tmp-cert-dir + serviceAccountName: dynatrace-operator + securityContext: + {{- toYaml .Values.operator.podSecurityContext | nindent 8 }} + {{- if .Values.customPullSecret }} + imagePullSecrets: + - name: {{ .Values.customPullSecret }} + {{- end }} + {{- if .Values.operator.nodeSelector }} + nodeSelector: {{- toYaml .Values.operator.nodeSelector | nindent 8 }} + {{- end }} + tolerations: + {{- if .Values.operator.tolerations }} + {{- toYaml .Values.operator.tolerations | nindent 8 }} + {{- end }} + {{- include "dynatrace-operator.defaultTolerations" . | nindent 8 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/role-operator.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/role-operator.yaml new file mode 100644 index 0000000000..d966ec8c0a --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/role-operator.yaml @@ -0,0 +1,170 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: dynatrace-operator + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} +rules: + - apiGroups: + - dynatrace.com + resources: + - dynakubes + - edgeconnects + verbs: + - get + - list + - watch + - update + - create + - apiGroups: + - dynatrace.com + resources: + - dynakubes/finalizers + - dynakubes/status + - edgeconnects/finalizers + - edgeconnects/status + verbs: + - update + - apiGroups: + - apps + resources: + - statefulsets + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - apps + resources: + - replicasets + - deployments + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - apps + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch + - create + - update + - delete + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - apiGroups: + - "" + resources: + - services + verbs: + - create + - update + - delete + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods/log + verbs: + - get + - apiGroups: + - networking.istio.io + resources: + - serviceentries + - virtualservices + verbs: + - get + - list + - create + - update + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - update + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: dynatrace-operator + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-operator +roleRef: + kind: Role + name: dynatrace-operator + apiGroup: rbac.authorization.k8s.io diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/serviceaccount-operator.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/serviceaccount-operator.yaml new file mode 100644 index 0000000000..0dfb23aed9 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/operator/serviceaccount-operator.yaml @@ -0,0 +1,20 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-operator + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/clusterrole-webhook.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/clusterrole-webhook.yaml new file mode 100644 index 0000000000..953802aeb3 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/clusterrole-webhook.yaml @@ -0,0 +1,102 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dynatrace-webhook + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch + - update + - apiGroups: + - "" + resources: + - secrets + verbs: + - create + - apiGroups: + - "" + resources: + - secrets + resourceNames: + - dynatrace-dynakube-config + - dynatrace-metadata-enrichment-endpoint + verbs: + - get + - list + - watch + - update + # metadata-enrichment workload owner lookup + - apiGroups: + - "" + resources: + - replicationcontrollers + verbs: + - get + - apiGroups: + - apps + resources: + - replicasets + - statefulsets + - daemonsets + - deployments + verbs: + - get + - apiGroups: + - batch + resources: + - jobs + - cronjobs + verbs: + - get + - apiGroups: + - apps.openshift.io + resources: + - deploymentconfigs + verbs: + - get + {{- if (eq (include "dynatrace-operator.openshiftOrOlm" .) "true") }} + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + - nonroot-v2 + resources: + - securitycontextconstraints + verbs: + - use + {{ end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dynatrace-webhook + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: dynatrace-webhook + apiGroup: rbac.authorization.k8s.io diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/deployment-webhook.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/deployment-webhook.yaml new file mode 100644 index 0000000000..f63530e867 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/deployment-webhook.yaml @@ -0,0 +1,138 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + annotations: + {{- if .Values.webhook.annotations}} + {{- toYaml .Values.webhook.annotations | nindent 4 }} + {{- end }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} + {{- if .Values.webhook.labels }} + {{- toYaml .Values.webhook.labels | nindent 4 }} + {{- end }} +spec: + replicas: {{ (default false (.Values.webhook).highAvailability) | ternary 2 1 }} + revisionHistoryLimit: 1 + selector: + matchLabels: + {{- include "dynatrace-operator.webhookSelectorLabels" . | nindent 6 }} + strategy: + type: RollingUpdate + template: + metadata: + annotations: + dynatrace.com/inject: "false" + kubectl.kubernetes.io/default-container: webhook + {{- if (.Values.webhook).apparmor}} + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default + {{- end }} + {{- if .Values.webhook.annotations}} + {{- toYaml .Values.webhook.annotations | nindent 8 }} + {{- end }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 8 }} + {{- include "dynatrace-operator.webhookSelectorLabels" . | nindent 8 }} + {{- if .Values.webhook.labels }} + {{- toYaml .Values.webhook.labels | nindent 8 }} + {{- end }} + spec: + {{- if (.Values.webhook).highAvailability }} + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: "topology.kubernetes.io/zone" + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + {{- include "dynatrace-operator.webhookSelectorLabels" . | nindent 14 }} + - maxSkew: 1 + topologyKey: "kubernetes.io/hostname" + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + {{- include "dynatrace-operator.webhookSelectorLabels" . | nindent 14 }} + {{- end }} + volumes: + - emptyDir: {} + name: certs-dir + {{- include "dynatrace-operator.nodeAffinity" . | nindent 6 }} + containers: + - name: webhook + args: + - webhook-server + # OLM mounts the certificates here, so we reuse it for simplicity + - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ + image: {{ include "dynatrace-operator.image" . }} + imagePullPolicy: Always + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + readinessProbe: + httpGet: + path: /readyz + port: livez + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 10 + livenessProbe: + httpGet: + path: /livez + port: livez + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 10 + ports: + - name: server-port + containerPort: 8443 + - name: livez + containerPort: 10080 + - name: metrics + containerPort: 8080 + resources: + requests: + {{- toYaml (.Values.webhook).requests | nindent 14 }} + limits: + {{- toYaml (.Values.webhook).limits | nindent 14 }} + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + {{- toYaml .Values.webhook.securityContext | nindent 12 }} + serviceAccountName: dynatrace-webhook + {{- if (.Values.webhook).hostNetwork }} + hostNetwork: true + {{- end }} + securityContext: + {{- toYaml .Values.webhook.podSecurityContext | nindent 8 }} + {{- if .Values.customPullSecret }} + imagePullSecrets: + - name: {{ .Values.customPullSecret }} + {{- end }} + {{- if .Values.webhook.nodeSelector }} + nodeSelector: {{- toYaml .Values.webhook.nodeSelector | nindent 8 }} + {{- end }} + tolerations: + {{- if .Values.webhook.tolerations }} + {{- toYaml .Values.webhook.tolerations | nindent 8 }} + {{- end }} + {{- include "dynatrace-operator.defaultTolerations" . | nindent 8 }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/mutatingwebhookconfiguration.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/mutatingwebhookconfiguration.yaml new file mode 100644 index 0000000000..c7ec1baa53 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/mutatingwebhookconfiguration.yaml @@ -0,0 +1,58 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: dynatrace-webhook + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +webhooks: + - name: webhook.pod.dynatrace.com + reinvocationPolicy: IfNeeded + failurePolicy: {{.Values.webhook.mutatingWebhook.failurePolicy}} + timeoutSeconds: {{.Values.webhook.mutatingWebhook.timeoutSeconds}} + rules: + - apiGroups: [ "" ] + apiVersions: [ "v1" ] + operations: [ "CREATE" ] + resources: [ "pods" ] + scope: Namespaced + namespaceSelector: + matchExpressions: + - key: dynakube.internal.dynatrace.com/instance + operator: Exists + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /inject + admissionReviewVersions: [ "v1beta1", "v1" ] + sideEffects: None + - name: webhook.ns.dynatrace.com + reinvocationPolicy: IfNeeded + failurePolicy: {{.Values.webhook.mutatingWebhook.failurePolicy}} + timeoutSeconds: {{.Values.webhook.mutatingWebhook.timeoutSeconds}} + rules: + - apiGroups: [ "" ] + apiVersions: [ "v1" ] + operations: [ "CREATE", "UPDATE"] + resources: [ "namespaces" ] + scope: Cluster + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /label-ns + admissionReviewVersions: [ "v1beta1", "v1" ] + sideEffects: None diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/poddisruptionbudget-webhook.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/poddisruptionbudget-webhook.yaml new file mode 100644 index 0000000000..cc188e4495 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/poddisruptionbudget-webhook.yaml @@ -0,0 +1,11 @@ +# v1 version supported since k8s 1.21 +apiVersion: {{ .Capabilities.APIVersions.Has "policy/v1" | ternary "policy/v1" "policy/v1beta1" }} +kind: PodDisruptionBudget +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} +spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/component: webhook diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/role-webhook.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/role-webhook.yaml new file mode 100644 index 0000000000..1251ae47c3 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/role-webhook.yaml @@ -0,0 +1,70 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch + - apiGroups: + - "" + resources: + - secrets + - pods + - configmaps + verbs: + - get + - list + - watch + - apiGroups: + - dynatrace.com + resources: + - dynakubes + verbs: + - get + - list + - watch + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} +roleRef: + kind: Role + name: dynatrace-webhook + apiGroup: rbac.authorization.k8s.io diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/service.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/service.yaml new file mode 100644 index 0000000000..5e0c94c1b4 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/service.yaml @@ -0,0 +1,27 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: Service +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +spec: + selector: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} + ports: + - port: 443 + protocol: TCP + targetPort: server-port diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/serviceaccount-webhook.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/serviceaccount-webhook.yaml new file mode 100644 index 0000000000..d932bcca18 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/serviceaccount-webhook.yaml @@ -0,0 +1,21 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} + diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/validatingwebhookconfiguration.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/validatingwebhookconfiguration.yaml new file mode 100644 index 0000000000..f6c6cc8685 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/Common/webhook/validatingwebhookconfiguration.yaml @@ -0,0 +1,104 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: dynatrace-webhook + labels: + {{- include "dynatrace-operator.webhookLabels" . | nindent 4 }} +webhooks: + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /validate-dynatrace-com-v1beta1-dynakube + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1beta1 + resources: + - dynakubes + name: v1beta1.dynakube.webhook.dynatrace.com + timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} + sideEffects: None + matchPolicy: Exact + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /validate-dynatrace-com-v1beta2-dynakube + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1beta2 + resources: + - dynakubes + name: v1beta2.dynakube.webhook.dynatrace.com + timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} + sideEffects: None + matchPolicy: Exact + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /validate-dynatrace-com-v1alpha1-edgeconnect + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1alpha1 + resources: + - edgeconnects + name: v1alpha1.edgeconnect.webhook.dynatrace.com + timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} + sideEffects: None + matchPolicy: Exact + - admissionReviewVersions: + - v1 + clientConfig: + service: + name: dynatrace-webhook + namespace: {{ .Release.Namespace }} + path: /validate-dynatrace-com-v1alpha2-edgeconnect + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - dynatrace.com + apiVersions: + - v1alpha2 + resources: + - edgeconnects + name: v1alpha2.edgeconnect.webhook.dynatrace.com + timeoutSeconds: {{.Values.webhook.validatingWebhook.timeoutSeconds}} + sideEffects: None + matchPolicy: Exact diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/NOTES.txt b/charts/dynatrace/dynatrace-operator/1.3.0/templates/NOTES.txt new file mode 100644 index 0000000000..48d4f09fc9 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/NOTES.txt @@ -0,0 +1,10 @@ +Thank you for installing {{ .Chart.Name }}. + +Your release is named {{ .Release.Name }}. + +To find more information about the Dynatrace Operator, try: +https://github.com/Dynatrace/dynatrace-operator + +To verify the current state of the deployments, try: + $ kubectl get pods -n {{ .Release.Namespace }} + $ kubectl logs -f deployment/dynatrace-operator -n {{ .Release.Namespace }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/_csidriver.tpl b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_csidriver.tpl new file mode 100644 index 0000000000..08ee79fb5d --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_csidriver.tpl @@ -0,0 +1,74 @@ +// Copyright 2020 Dynatrace LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{{/* +Check if we need the csi driver. +*/}} +{{- define "dynatrace-operator.needCSI" -}} + {{- if or (.Values.csidriver.enabled) -}} + {{- printf "true" -}} + {{- end -}} +{{- end -}} + +{{/* +CSI PriorityClassName +*/}} +{{- define "dynatrace-operator.CSIPriorityClassName" -}} + {{- default "dynatrace-high-priority" .Values.csidriver.existingPriorityClassName -}} +{{- end -}} + +{{/* +Check if we need the csi default priority class +*/}} +{{- define "dynatrace-operator.needPriorityClass" -}} + {{- if and (eq (include "dynatrace-operator.needCSI" .) "true") (not .Values.csidriver.existingPriorityClassName) -}} + {{- printf "true" -}} + {{- end -}} +{{- end -}} + +{{/* +CSI plugin-dir path +*/}} +{{- define "dynatrace-operator.CSIPluginDir" -}} + {{ printf "%s/plugins/csi.oneagent.dynatrace.com/" (trimSuffix "/" (default "/var/lib/kubelet" .Values.csidriver.kubeletPath)) }} +{{- end -}} + + +{{/* +CSI data-dir path +*/}} +{{- define "dynatrace-operator.CSIDataDir" -}} + {{ printf "%s/data" (trimSuffix "/" (include "dynatrace-operator.CSIPluginDir" .)) }} +{{- end -}} + +{{/* +CSI socket path +*/}} +{{- define "dynatrace-operator.CSISocketPath" -}} + {{ printf "%s/csi.sock" (trimSuffix "/" (include "dynatrace-operator.CSIPluginDir" .)) }} +{{- end -}} + +{{/* +CSI mountpoint-dir path +*/}} +{{- define "dynatrace-operator.CSIMountPointDir" -}} + {{ printf "%s/pods/" (trimSuffix "/" (default "/var/lib/kubelet" .Values.csidriver.kubeletPath)) }} +{{- end -}} + +{{/* +CSI registration-dir path +*/}} +{{- define "dynatrace-operator.CSIRegistrationDir" -}} + {{ printf "%s/plugins_registry/" (trimSuffix "/" (default "/var/lib/kubelet" .Values.csidriver.kubeletPath)) }} +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/_helpers.tpl b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_helpers.tpl new file mode 100644 index 0000000000..1f17f80685 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_helpers.tpl @@ -0,0 +1,53 @@ +// Copyright 2020 Dynatrace LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "dynatrace-operator.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Check if default image or imageref is used +*/}} +{{- define "dynatrace-operator.image" -}} +{{- if .Values.image -}} + {{- printf "%s" .Values.image -}} +{{- else -}} + {{- if (.Values.imageRef).repository -}} + {{- .Values.imageRef.tag | default (printf "v%s" .Chart.AppVersion) | printf "%s:%s" .Values.imageRef.repository -}} + {{- else if eq (include "dynatrace-operator.platform" .) "openshift" -}} + {{- printf "%s:v%s" "registry.connect.redhat.com/dynatrace/dynatrace-operator" .Chart.AppVersion }} + {{- else if eq (include "dynatrace-operator.platform" .) "google-marketplace" -}} + {{- printf "%s:%s" "gcr.io/dynatrace-marketplace-prod/dynatrace-operator" .Chart.AppVersion }} + {{- else if eq (include "dynatrace-operator.platform" .) "azure-marketplace" -}} + {{- printf "%s/%s@%s" .Values.global.azure.images.operator.registry .Values.global.azure.images.operator.image .Values.global.azure.images.operator.digest }} + {{- else -}} + {{- printf "%s:v%s" "public.ecr.aws/dynatrace/dynatrace-operator" .Chart.AppVersion }} + {{- end -}} +{{- end -}} +{{- end -}} + +{{- define "dynatrace-operator.startupProbe" -}} +startupProbe: + exec: + command: + - /usr/local/bin/dynatrace-operator + - startup-probe + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 1 +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/_labels.tpl b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_labels.tpl new file mode 100644 index 0000000000..e66473db01 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_labels.tpl @@ -0,0 +1,102 @@ +// Copyright 2020 Dynatrace LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{{/* +Selector labels +*/}} +{{- define "dynatrace-operator.futureSelectorLabels" -}} +app.kubernetes.io/name: dynatrace-operator +{{- if not (.Values).manifests }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "dynatrace-operator.commonLabels" -}} +{{ include "dynatrace-operator.futureSelectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +{{- if not (.Values).manifests }} +helm.sh/chart: {{ include "dynatrace-operator.chart" . }} +{{- end -}} +{{- if eq (include "dynatrace-operator.platform" .) "azure-marketplace" }} +azure-extensions-usage-release-identifier: {{ .Release.Name | quote }} +{{- end -}} +{{- end -}} + +{{/* +Operator labels +*/}} +{{- define "dynatrace-operator.operatorLabels" -}} +{{ include "dynatrace-operator.commonLabels" . }} +app.kubernetes.io/component: operator +{{- end -}} + +{{/* +Operator selector labels +*/}} +{{- define "dynatrace-operator.operatorSelectorLabels" -}} +name: {{ .Release.Name }} +{{- end -}} + +{{/* +Webhook labels +*/}} +{{- define "dynatrace-operator.webhookLabels" -}} +{{ include "dynatrace-operator.commonLabels" . }} +app.kubernetes.io/component: webhook +{{- end -}} + +{{/* +Webhook selector labels +*/}} +{{- define "dynatrace-operator.webhookSelectorLabels" -}} +internal.dynatrace.com/component: webhook +internal.dynatrace.com/app: webhook +{{- end -}} + +{{/* +CSI labels +*/}} +{{- define "dynatrace-operator.csiLabels" -}} +{{ include "dynatrace-operator.commonLabels" . }} +app.kubernetes.io/component: csi-driver +{{- end -}} + +{{/* +CSI selector labels +*/}} +{{- define "dynatrace-operator.csiSelectorLabels" -}} +internal.oneagent.dynatrace.com/app: csi-driver +internal.oneagent.dynatrace.com/component: csi-driver +{{- end -}} + +{{/* +ActiveGate labels +*/}} +{{- define "dynatrace-operator.activegateLabels" -}} +{{ include "dynatrace-operator.commonLabels" . }} +app.kubernetes.io/component: activegate +{{- end -}} + +{{/* +OneAgent labels +*/}} +{{- define "dynatrace-operator.oneagentLabels" -}} +{{ include "dynatrace-operator.commonLabels" . }} +app.kubernetes.io/component: oneagent +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/_platform.tpl b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_platform.tpl new file mode 100644 index 0000000000..2080d801e0 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/_platform.tpl @@ -0,0 +1,84 @@ +// Copyright 2020 Dynatrace LLC + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{{/* +Auto-detect the platform (if not set), according to the available APIVersions +*/}} +{{- define "dynatrace-operator.platform" -}} + {{- if .Values.platform}} + {{- printf .Values.platform -}} + {{- else if .Capabilities.APIVersions.Has "security.openshift.io/v1" }} + {{- printf "openshift" -}} + {{- else }} + {{- printf "kubernetes" -}} + {{- end -}} +{{- end }} + +{{/* +Set install source how the Operator was installed +*/}} +{{- define "dynatrace-operator.installSource" -}} + {{- if .Values.olm }} + {{- printf "operatorhub" -}} + {{- else if .Values.manifests }} + {{- printf "manifest" -}} + {{- else if (and (.Values.platform) (not (has .Values.platform (list "kubernetes" "openshift")))) }} + {{- printf .Values.platform -}} + {{- else }} + {{- printf "helm" -}} + {{- end -}} +{{- end }} + +{{/* +Exclude Kubernetes manifest not running on OLM +*/}} +{{- define "dynatrace-operator.openshiftOrOlm" -}} +{{- if and (or (eq (include "dynatrace-operator.platform" .) "openshift") (.Values.olm)) -}} + {{ default "true" }} +{{- end -}} +{{- end -}} + +{{- define "dynatrace-operator.nodeAffinity" -}} +affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - s390x + - key: kubernetes.io/os + operator: In + values: + - linux +{{- end -}} + +{{- define "dynatrace-operator.defaultTolerations" -}} +- key: kubernetes.io/arch + value: arm64 + effect: NoSchedule +- key: kubernetes.io/arch + value: amd64 + effect: NoSchedule +- key: kubernetes.io/arch + value: ppc64le + effect: NoSchedule +- key: kubernetes.io/arch + value: s390x + effect: NoSchedule +{{- end -}} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/templates/application.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/templates/application.yaml new file mode 100644 index 0000000000..1dd17410d1 --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/templates/application.yaml @@ -0,0 +1,98 @@ +{{- if eq (include "dynatrace-operator.platform" .) "google-marketplace" }} +# Copyright 2020 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: app.k8s.io/v1beta1 +kind: Application +metadata: + name: {{ .Release.Name }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "dynatrace-operator.operatorLabels" . | nindent 4 }} + annotations: + kubernetes-engine.cloud.google.com/icon: data:image/png;base64,{{ .Files.Get "logo.png" | b64enc }} + marketplace.cloud.google.com/deploy-info: '{"partner_id": "dynatrace-marketplace-prod", "product_id": "dynatrace-operator", "partner_name": "Dynatrace LLC"}' +spec: + descriptor: + type: "Dynatrace Operator" + version: {{ .Chart.AppVersion }} + maintainers: + - name: Dynatrace LLC + url: https://www.dynatrace.com/ + keywords: + - "dynatrace" + - "operator" + - "activegate" + - "k8s" + - "monitoring" + - "apm" + description: | + # Dynatrace Operator + + The Dynatrace Operator supports rollout and lifecycle management of various Dynatrace components in Kubernetes and OpenShift. + + * OneAgent + * `classicFullStack` rolls out a OneAgent pod per node to monitor pods on it and the node itself + * `applicationMonitoring` is a webhook based injection mechanism for automatic app-only injection + * CSI Driver can be enabled to cache OneAgent downloads per node + * `hostMonitoring` is only monitoring the hosts (i.e. nodes) in the cluster without app-only injection + * `cloudNativeFullStack` is a combination of `applicationMonitoring` with CSI driver and `hostMonitoring` + * ActiveGate + * `routing` routes OneAgent traffic through the ActiveGate + * `kubernetes-monitoring` allows monitoring of the Kubernetes API + * `metrics-ingest` routes enriched metrics through ActiveGate + + For more information please have a look at [our DynaKube Custom Resource examples](config/samples) and + our [official help page](https://www.dynatrace.com/support/help/setup-and-configuration/setup-on-container-platforms/kubernetes/). + links: + - description: Dynatrace Website + url: https://www.dynatrace.com/ + - description: Operator Deploy Guide + url: ToDo + - description: Kubernetes Monitoring Info + url: https://www.dynatrace.com/technologies/kubernetes-monitoring + selector: + matchLabels: + app.kubernetes.io/name: dynatrace-operator + componentKinds: + - group: apps/v1 + kind: DaemonSet + - group: v1 + kind: Pod + - group: v1 + kind: ConfigMap + - group: apps/v1 + kind: Deployment + - group: v1 + kind: Secret + - group: batch/v1 + kind: Job + - group: v1 + kind: Service + - group: v1 + kind: ServiceAccount + - group: admissionregistration.k8s.io/v1 + kind: ValidatingWebhookConfiguration + - group: admissionregistration.k8s.io/v1 + kind: MutatingWebhookConfiguration + - group: apps/v1 + kind: StatefulSet + - group: storage.k8s.io/v1 + kind: CSIDriver + - group: rbac.authorization.k8s.io/v1 + kind: ClusterRole + - group: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + - group: rbac.authorization.k8s.io/v1 + kind: Role + - group: rbac.authorization.k8s.io/v1 + kind: RoleBinding +{{ end }} diff --git a/charts/dynatrace/dynatrace-operator/1.3.0/values.yaml b/charts/dynatrace/dynatrace-operator/1.3.0/values.yaml new file mode 100644 index 0000000000..0c484e7bab --- /dev/null +++ b/charts/dynatrace/dynatrace-operator/1.3.0/values.yaml @@ -0,0 +1,196 @@ +# Copyright 2021 Dynatrace LLC + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# special handling for "openshift" and "gke-autopilot" (deprecated) +platform: "" + +#image qualifier; OBSOLETE -> use imageref instead! +# supply either image or imageref; if both supplied, imageref will be disregarded +image: "" +#image description using tags +#resulting image will be named :v +imageRef: + repository: "" #path to repo + tag: "" #defaults to chart version + +customPullSecret: "" +installCRD: true + +operator: + nodeSelector: {} + tolerations: [] + labels: {} + annotations: {} + apparmor: false + securityContext: + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 1001 + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + podSecurityContext: + seccompProfile: + type: RuntimeDefault + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + +webhook: + hostNetwork: false + nodeSelector: {} + tolerations: [] + labels: {} + annotations: {} + apparmor: false + securityContext: + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 1001 + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + podSecurityContext: + seccompProfile: + type: RuntimeDefault + requests: + cpu: 300m + memory: 128Mi + limits: + cpu: 300m + memory: 128Mi + highAvailability: true + validatingWebhook: + timeoutSeconds: 10 + mutatingWebhook: + failurePolicy: Ignore + timeoutSeconds: 10 + +csidriver: + enabled: true + nodeSelector: {} + kubeletPath: "/var/lib/kubelet" + existingPriorityClassName: "" # if defined, use this priorityclass instead of creating a new one + priorityClassValue: "1000000" + maxUnmountedVolumeAge: "" # defined in days, must be a plain number + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + labels: {} + annotations: {} + updateStrategy: + rollingUpdate: + maxSurge: 0 + maxUnavailable: 1 + type: RollingUpdate + csiInit: + securityContext: + runAsUser: 0 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: false + seLinuxOptions: + level: s0 + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 50m + memory: 100Mi + server: + securityContext: + runAsUser: 0 + privileged: true # Needed for mountPropagation + allowPrivilegeEscalation: true # Needed for privileged + readOnlyRootFilesystem: true + runAsNonRoot: false + seLinuxOptions: + level: s0 + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 50m + memory: 100Mi + limits: + cpu: 50m + memory: 100Mi + provisioner: + securityContext: + runAsUser: 0 + privileged: true # Needed for mountPropagation + allowPrivilegeEscalation: true # Needed for privileged + readOnlyRootFilesystem: true + runAsNonRoot: false + seLinuxOptions: + level: s0 + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 300m + memory: 100Mi + registrar: + securityContext: + runAsUser: 0 + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 20m + memory: 30Mi + limits: + cpu: 20m + memory: 30Mi + livenessprobe: + securityContext: + runAsUser: 0 + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: false + seccompProfile: + type: RuntimeDefault + resources: + requests: + cpu: 20m + memory: 30Mi + limits: + cpu: 20m + memory: 30Mi + diff --git a/charts/speedscale/speedscale-operator/2.2.425/.helmignore b/charts/speedscale/speedscale-operator/2.2.425/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/speedscale/speedscale-operator/2.2.425/Chart.yaml b/charts/speedscale/speedscale-operator/2.2.425/Chart.yaml new file mode 100644 index 0000000000..55a4d5de0f --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/Chart.yaml @@ -0,0 +1,27 @@ +annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Speedscale Operator + catalog.cattle.io/kube-version: '>= 1.17.0-0' + catalog.cattle.io/release-name: speedscale-operator +apiVersion: v1 +appVersion: 2.2.425 +description: Stress test your APIs with real world scenarios. Collect and replay + traffic without scripting. +home: https://speedscale.com +icon: file://assets/icons/speedscale-operator.png +keywords: +- speedscale +- test +- testing +- regression +- reliability +- load +- replay +- network +- traffic +kubeVersion: '>= 1.17.0-0' +maintainers: +- email: support@speedscale.com + name: Speedscale Support +name: speedscale-operator +version: 2.2.425 diff --git a/charts/speedscale/speedscale-operator/2.2.425/LICENSE b/charts/speedscale/speedscale-operator/2.2.425/LICENSE new file mode 100644 index 0000000000..b78723d62f --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 Speedscale + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/charts/speedscale/speedscale-operator/2.2.425/README.md b/charts/speedscale/speedscale-operator/2.2.425/README.md new file mode 100644 index 0000000000..6ca25eed9d --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/README.md @@ -0,0 +1,111 @@ +![GitHub Tag](https://img.shields.io/github/v/tag/speedscale/operator-helm) + + +# Speedscale Operator + +The [Speedscale](https://www.speedscale.com) Operator is a [Kubernetes operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) +that watches for deployments to be applied to the cluster and takes action based on annotations. The operator +can inject a proxy to capture traffic into or out of applications, or setup an isolation test environment around +a deployment for testing. The operator itself is a deployment that will be always present on the cluster once +the helm chart is installed. + +## Prerequisites + +- Kubernetes 1.20+ +- Helm 3+ +- Appropriate [network and firewall configuration](https://docs.speedscale.com/reference/networking) for Speedscale cloud and webhook traffic + +## Get Repo Info + +```bash +helm repo add speedscale https://speedscale.github.io/operator-helm/ +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Install Chart + +An API key is required. Sign up for a [free Speedscale trial](https://speedscale.com/free-trial/) if you do not have one. + +```bash +helm install speedscale-operator speedscale/speedscale-operator \ + -n speedscale \ + --create-namespace \ + --set apiKey= \ + --set clusterName= +``` + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Pre-install job failure + +We use pre-install job to check provided API key and provision some of the required resources. + +If the job failed during the installation, you'll see the following error during install: + +``` +Error: INSTALLATION FAILED: failed pre-install: job failed: BackoffLimitExceeded +``` + +You can inspect the logs using this command: + +```bash +kubectl -n speedscale logs job/speedscale-operator-pre-install +``` + +After fixing the error, uninstall the helm release, delete the failed job +and try installing again: + +```bash +helm -n speedscale uninstall speedscale-operator +kubectl -n speedscale delete job speedscale-operator-pre-install +``` + +## Uninstall Chart + +```bash +helm -n speedscale uninstall speedscale-operator +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +CRDs created by this chart are not removed by default and should be manually cleaned up: + +```bash +kubectl delete crd trafficreplays.speedscale.com +``` + +## Upgrading Chart + +```bash +helm repo update +helm -n speedscale upgrade speedscale-operator speedscale/speedscale-operator +``` + +Resources capturing traffic will need to be rolled to pick up the latest +Speedscale sidecar. Use the rollout restart command for each namespace and +resource type: + +```bash +kubectl -n rollout restart deployment +``` + +With Helm v3, CRDs created by this chart are not updated by default +and should be manually updated. +Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Upgrading an existing Release to a new version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an +incompatible breaking change needing manual actions. + + +## Help + +Speedscale docs information available at [docs.speedscale.com](https://docs.speedscale.com) or join us +on the [Speedscale community Slack](https://join.slack.com/t/speedscalecommunity/shared_invite/zt-x5rcrzn4-XHG1QqcHNXIM~4yozRrz8A)! diff --git a/charts/speedscale/speedscale-operator/2.2.425/app-readme.md b/charts/speedscale/speedscale-operator/2.2.425/app-readme.md new file mode 100644 index 0000000000..6ca25eed9d --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/app-readme.md @@ -0,0 +1,111 @@ +![GitHub Tag](https://img.shields.io/github/v/tag/speedscale/operator-helm) + + +# Speedscale Operator + +The [Speedscale](https://www.speedscale.com) Operator is a [Kubernetes operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) +that watches for deployments to be applied to the cluster and takes action based on annotations. The operator +can inject a proxy to capture traffic into or out of applications, or setup an isolation test environment around +a deployment for testing. The operator itself is a deployment that will be always present on the cluster once +the helm chart is installed. + +## Prerequisites + +- Kubernetes 1.20+ +- Helm 3+ +- Appropriate [network and firewall configuration](https://docs.speedscale.com/reference/networking) for Speedscale cloud and webhook traffic + +## Get Repo Info + +```bash +helm repo add speedscale https://speedscale.github.io/operator-helm/ +helm repo update +``` + +_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._ + +## Install Chart + +An API key is required. Sign up for a [free Speedscale trial](https://speedscale.com/free-trial/) if you do not have one. + +```bash +helm install speedscale-operator speedscale/speedscale-operator \ + -n speedscale \ + --create-namespace \ + --set apiKey= \ + --set clusterName= +``` + +_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ + +### Pre-install job failure + +We use pre-install job to check provided API key and provision some of the required resources. + +If the job failed during the installation, you'll see the following error during install: + +``` +Error: INSTALLATION FAILED: failed pre-install: job failed: BackoffLimitExceeded +``` + +You can inspect the logs using this command: + +```bash +kubectl -n speedscale logs job/speedscale-operator-pre-install +``` + +After fixing the error, uninstall the helm release, delete the failed job +and try installing again: + +```bash +helm -n speedscale uninstall speedscale-operator +kubectl -n speedscale delete job speedscale-operator-pre-install +``` + +## Uninstall Chart + +```bash +helm -n speedscale uninstall speedscale-operator +``` + +This removes all the Kubernetes components associated with the chart and deletes the release. + +_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ + +CRDs created by this chart are not removed by default and should be manually cleaned up: + +```bash +kubectl delete crd trafficreplays.speedscale.com +``` + +## Upgrading Chart + +```bash +helm repo update +helm -n speedscale upgrade speedscale-operator speedscale/speedscale-operator +``` + +Resources capturing traffic will need to be rolled to pick up the latest +Speedscale sidecar. Use the rollout restart command for each namespace and +resource type: + +```bash +kubectl -n rollout restart deployment +``` + +With Helm v3, CRDs created by this chart are not updated by default +and should be manually updated. +Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions). + +_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ + +### Upgrading an existing Release to a new version + +A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an +incompatible breaking change needing manual actions. + + +## Help + +Speedscale docs information available at [docs.speedscale.com](https://docs.speedscale.com) or join us +on the [Speedscale community Slack](https://join.slack.com/t/speedscalecommunity/shared_invite/zt-x5rcrzn4-XHG1QqcHNXIM~4yozRrz8A)! diff --git a/charts/speedscale/speedscale-operator/2.2.425/questions.yaml b/charts/speedscale/speedscale-operator/2.2.425/questions.yaml new file mode 100644 index 0000000000..29aee38958 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/questions.yaml @@ -0,0 +1,9 @@ +questions: +- variable: apiKey + default: "fffffffffffffffffffffffffffffffffffffffffffff" + description: "An API key is required to connect to the Speedscale cloud." + required: true + type: string + label: API Key + group: Authentication + diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/NOTES.txt b/charts/speedscale/speedscale-operator/2.2.425/templates/NOTES.txt new file mode 100644 index 0000000000..cabb59b175 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/NOTES.txt @@ -0,0 +1,12 @@ +Thank you for installing the Speedscale Operator! + +Next you'll need to add the Speedscale Proxy Sidecar to your deployments. +See https://docs.speedscale.com/setup/sidecar/install/ + +If upgrading use the rollout restart command for each namespace and resource +type to ensure Speedscale sidecars are updated: + + kubectl -n rollout restart deployment + +Once your deployment is running the sidecar your service will show up on +https://app.speedscale.com/. diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/admission.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/admission.yaml new file mode 100644 index 0000000000..301748a61d --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/admission.yaml @@ -0,0 +1,209 @@ +{{- $cacrt := "" -}} +{{- $crt := "" -}} +{{- $key := "" -}} +{{- $s := (lookup "v1" "Secret" .Release.Namespace "speedscale-webhook-certs") -}} +{{- if $s -}} +{{- $cacrt = index $s.data "ca.crt" | default (index $s.data "tls.crt") | b64dec -}} +{{- $crt = index $s.data "tls.crt" | b64dec -}} +{{- $key = index $s.data "tls.key" | b64dec -}} +{{ else }} +{{- $altNames := list ( printf "speedscale-operator.%s" .Release.Namespace ) ( printf "speedscale-operator.%s.svc" .Release.Namespace ) -}} +{{- $ca := genCA "speedscale-operator" 3650 -}} +{{- $cert := genSignedCert "speedscale-operator" nil $altNames 3650 $ca -}} +{{- $cacrt = $ca.Cert -}} +{{- $crt = $cert.Cert -}} +{{- $key = $cert.Key -}} +{{- end -}} +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + creationTimestamp: null + name: speedscale-operator + annotations: + argocd.argoproj.io/hook: PreSync + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $cacrt | b64enc }} + service: + name: speedscale-operator + namespace: {{ .Release.Namespace }} + path: /mutate + failurePolicy: Ignore + name: sidecar.speedscale.com + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: "NotIn" + values: + - kube-system + - kube-node-lease + {{- if .Values.namespaceSelector }} + - key: kubernetes.io/metadata.name + operator: "In" + values: + {{- range .Values.namespaceSelector }} + - {{ . | quote }} + {{- end }} + {{- end }} + reinvocationPolicy: IfNeeded + rules: + - apiGroups: + - apps + - batch + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - deployments + - statefulsets + - daemonsets + - jobs + - replicasets + - apiGroups: + - "" + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - pods + - apiGroups: + - argoproj.io + apiVersions: + - "*" + operations: + - CREATE + - UPDATE + - DELETE + resources: + - rollouts + sideEffects: None + timeoutSeconds: 10 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + creationTimestamp: null + name: speedscale-operator-replay + annotations: + argocd.argoproj.io/hook: PreSync + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $cacrt | b64enc }} + service: + name: speedscale-operator + namespace: {{ .Release.Namespace }} + path: /mutate-speedscale-com-v1-trafficreplay + failurePolicy: Fail + name: replay.speedscale.com + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: "NotIn" + values: + - kube-system + - kube-node-lease + {{- if .Values.namespaceSelector }} + - key: kubernetes.io/metadata.name + operator: "In" + values: + {{- range .Values.namespaceSelector }} + - {{ . | quote }} + {{- end }} + {{- end }} + rules: + - apiGroups: + - speedscale.com + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - trafficreplays + sideEffects: None + timeoutSeconds: 10 +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: speedscale-operator-replay + annotations: + argocd.argoproj.io/hook: PreSync + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + caBundle: {{ $cacrt | b64enc }} + service: + name: speedscale-operator + namespace: {{ .Release.Namespace }} + path: /validate-speedscale-com-v1-trafficreplay + failurePolicy: Fail + name: replay.speedscale.com + namespaceSelector: + matchExpressions: + - key: kubernetes.io/metadata.name + operator: "NotIn" + values: + - kube-system + - kube-node-lease + {{- if .Values.namespaceSelector }} + - key: kubernetes.io/metadata.name + operator: "In" + values: + {{- range .Values.namespaceSelector }} + - {{ . | quote }} + {{- end }} + {{- end }} + rules: + - apiGroups: + - speedscale.com + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - trafficreplays + sideEffects: None + timeoutSeconds: 10 +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + name: speedscale-webhook-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + ca.crt: {{ $cacrt | b64enc }} + tls.crt: {{ $crt | b64enc }} + tls.key: {{ $key | b64enc }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/configmap.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/configmap.yaml new file mode 100644 index 0000000000..04dfda91aa --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/configmap.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: speedscale-operator + namespace: {{ .Release.Namespace }} + annotations: + argocd.argoproj.io/hook: PreSync + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} +data: + CLUSTER_NAME: {{ .Values.clusterName }} + IMAGE_PULL_POLICY: {{ .Values.image.pullPolicy }} + IMAGE_PULL_SECRETS: "" + IMAGE_REGISTRY: {{ .Values.image.registry }} + IMAGE_TAG: {{ .Values.image.tag }} + INSTANCE_ID: '{{- $cm := (lookup "v1" "ConfigMap" .Release.Namespace "speedscale-operator") -}}{{ if $cm }}{{ $cm.data.INSTANCE_ID }}{{ else }}{{ ( printf "%s-%s" .Values.clusterName uuidv4 ) }}{{ end }}' + LOG_LEVEL: {{ .Values.logLevel }} + SPEEDSCALE_DLP_CONFIG: {{ .Values.dlp.config }} + SPEEDSCALE_FILTER_RULE: {{ .Values.filterRule }} + TELEMETRY_INTERVAL: 1s + WITH_DLP: {{ .Values.dlp.enabled | quote }} + WITH_INSPECTOR: {{ .Values.dashboardAccess | quote }} + API_KEY_SECRET_NAME: {{ .Values.apiKeySecret | quote }} + DEPLOY_DEMO: {{ .Values.deployDemo | quote }} + GLOBAL_ANNOTATIONS: {{ .Values.globalAnnotations | toJson | quote }} + GLOBAL_LABELS: {{ .Values.globalLabels | toJson | quote }} + {{- if .Values.http_proxy }} + HTTP_PROXY: {{ .Values.http_proxy }} + {{- end }} + {{- if .Values.https_proxy }} + HTTPS_PROXY: {{ .Values.https_proxy }} + {{- end }} + {{- if .Values.no_proxy }} + NO_PROXY: {{ .Values.no_proxy }} + {{- end }} + PRIVILEGED_SIDECARS: {{ .Values.privilegedSidecars | quote }} + DISABLE_SMARTDNS: {{ .Values.disableSidecarSmartReverseDNS | quote }} + SIDECAR_CONFIG: {{ .Values.sidecar | toJson | quote }} + FORWARDER_CONFIG: {{ .Values.forwarder | toJson | quote }} + TEST_PREP_TIMEOUT: {{ .Values.operator.test_prep_timeout }} + CONTROL_PLANE_TIMEOUT: {{ .Values.operator.control_plane_timeout }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/crds/trafficreplays.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/crds/trafficreplays.yaml new file mode 100644 index 0000000000..1bee7e1576 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/crds/trafficreplays.yaml @@ -0,0 +1,523 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + creationTimestamp: null + name: trafficreplays.speedscale.com +spec: + group: speedscale.com + names: + kind: TrafficReplay + listKind: TrafficReplayList + plural: trafficreplays + shortNames: + - replay + singular: trafficreplay + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.active + name: Active + type: boolean + - jsonPath: .spec.mode + name: Mode + type: string + - jsonPath: .status.conditions[-1:].message + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: TrafficReplay is the Schema for the trafficreplays API + properties: + apiVersion: + 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 + type: string + kind: + 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 + type: string + metadata: + type: object + spec: + description: TrafficReplaySpec defines the desired state of TrafficReplay + properties: + buildTag: + description: |- + BuildTag links a unique tag, build hash, etc. to the generated + traffic replay report. That way you can connect the report results to the + version of the code that was tested. + type: string + cleanup: + description: |- + Cleanup is the name of cleanup mode used for this + TrafficReplay. + enum: + - inventory + - all + - none + type: string + collectLogs: + description: |- + CollectLogs enables or disables log collection from target + workload. Defaults to true. + DEPRECATED: use TestReport.ActualConfig.Cluster.CollectLogs + type: boolean + configChecksum: + description: |- + ConfigChecksum, managed my the operator, is the SHA1 checksum of the + configuration. + type: string + customURL: + description: |- + CustomURL specifies a custom URL to send *ALL* traffic to. Use + Workload.CustomURI to send traffic to a specific URL for only that + workload. + type: string + generatorLowData: + description: |- + GeneratorLowData forces the generator into a high + efficiency/low data output mode. This is ideal for high volume + performance tests. Defaults to false. + DEPRECATED + type: boolean + mode: + description: Mode is the name of replay mode used for this TrafficReplay. + enum: + - full-replay + - responder-only + - generator-only + type: string + needsReport: + description: Indicates whether a responder-only replay needs a report. + type: boolean + proxyMode: + description: |- + ProxyMode defines proxy operational mode used with injected sidecar. + DEPRECATED + type: string + responderLowData: + description: |- + ResponderLowData forces the responder into a high + efficiency/low data output mode. This is ideal for high volume + performance tests. Defaults to false. + DEPRECATED + type: boolean + secretRefs: + description: |- + SecretRefs hold the references to the secrets which contain + various secrets like (e.g. short-lived JWTs to be used by the generator + for authorization with HTTP calls). + items: + description: |- + LocalObjectReference contains enough information to locate the referenced + Kubernetes resource object. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + type: array + sidecar: + description: |- + Sidecar defines sidecar specific configuration. + DEPRECATED: use Workloads + properties: + inject: + description: 'DEPRECATED: do not use' + type: boolean + patch: + description: Patch is .yaml file patch for the Workload + format: byte + type: string + tls: + properties: + in: + description: In provides configuration for sidecar inbound + TLS. + properties: + private: + description: Private is the filename of the TLS inbound + private key. + type: string + public: + description: Public is the filename of the TLS inbound + public key. + type: string + secret: + description: Secret is a secret with the TLS keys to use + for inbound traffic. + type: string + type: object + mutual: + description: Mutual provides configuration for sidecar mutual + TLS. + properties: + private: + description: Private is the filename of the mutual TLS + private key. + type: string + public: + description: Public is the filename of the mutual TLS + public key. + type: string + secret: + description: Secret is a secret with the mutual TLS keys. + type: string + type: object + out: + description: |- + Out enables or disables TLS out on the + sidecar during replay. + type: boolean + type: object + type: object + snapshotID: + description: |- + SnapshotID is the id of the traffic snapshot for this + TrafficReplay. + type: string + testConfigID: + description: |- + TestConfigID is the id of the replay configuration to be used + by the generator and responder for the TrafficReplay. + type: string + timeout: + description: |- + Timeout is the time to wait for replay test to finish. Defaults + to value of the `TIMEOUT` setting of the operator. + type: string + ttlAfterReady: + description: |- + TTLAfterReady provides a TTL (time to live) mechanism to limit + the lifetime of TrafficReplay object that have finished the execution and + reached its final state (either complete or failed). + type: string + workloadRef: + description: |- + WorkloadRef is the reference to the target workload (SUT) for + TrafficReplay. The operations will be performed in the namespace of the + target object. + DEPRECATED: use Workloads + properties: + apiVersion: + description: API version of the referenced object. + type: string + kind: + description: Kind of the referenced object. Defaults to "Deployment". + type: string + name: + description: |- + Name of the referenced object. Required when defining for a test unless a + custom URI is provided. Always required when defining mocks. + type: string + namespace: + description: Namespace of the referenced object. Defaults to the + TrafficReplay namespace. + type: string + required: + - name + type: object + workloads: + description: |- + Workloads define target workloads (SUT) for a TrafficReplay. Many + workloads may be provided, or none. Workloads may be modified and + restarted during replay to configure communication with a responder. + items: + description: |- + Workload represents a Kubernetes workload to be targeted during replay and + associated settings. + properties: + customURI: + description: |- + CustomURI will be target of the traffic instead of directly targeting + workload. This is required if a Ref is not specified. + type: string + inTrafficKey: + description: 'DEPRECATED: use Tests' + type: string + inTrafficKeys: + description: 'DEPRECATED: use Tests' + items: + type: string + type: array + mocks: + description: |- + Mocks are strings used to identify slices of outbound snapshot traffic to + mock for this workload and maps directly to a snapshot's `OutTraffic` + field. Snapshot egress traffic can be split across multiple slices where + each slice contains part of the traffic. A workload may specify multiple + keys and multiple workloads may specify the same key. + + + Only the traffic slices defined here will be mocked. A workload with no + keys defined will not mock any traffic. Pass '*' to mock all traffic. + + + Mock strings may only match part of the snapshot's `OutTraffic` key if the + string matches exactly one key. For example, the test string + `foo.example.com` would match the `OutTraffic` key of + my-service:foo.example.com:8080, as long as no other keys would match + `foo.example.com`. Multiple mocks must be specified for multiple keys + unless using '*'. + items: + type: string + type: array + outTrafficKeys: + description: 'DEPRECATED: use Mocks' + items: + type: string + type: array + ref: + description: |- + Ref is a reference to a cluster workload, like a deployment or a + statefulset. This is required unless a CustomURI is specified. + properties: + apiVersion: + description: API version of the referenced object. + type: string + kind: + description: Kind of the referenced object. Defaults to + "Deployment". + type: string + name: + description: |- + Name of the referenced object. Required when defining for a test unless a + custom URI is provided. Always required when defining mocks. + type: string + namespace: + description: Namespace of the referenced object. Defaults + to the TrafficReplay namespace. + type: string + required: + - name + type: object + routing: + description: Routing configures how workloads route egress traffic + to responders + enum: + - hostalias + - nat + type: string + sidecar: + description: |- + TODO: this is not implemented, come back and replace deprecated Sidecar with workload specific settings + Sidecar defines sidecar specific configuration. + properties: + inject: + description: 'DEPRECATED: do not use' + type: boolean + patch: + description: Patch is .yaml file patch for the Workload + format: byte + type: string + tls: + properties: + in: + description: In provides configuration for sidecar inbound + TLS. + properties: + private: + description: Private is the filename of the TLS + inbound private key. + type: string + public: + description: Public is the filename of the TLS inbound + public key. + type: string + secret: + description: Secret is a secret with the TLS keys + to use for inbound traffic. + type: string + type: object + mutual: + description: Mutual provides configuration for sidecar + mutual TLS. + properties: + private: + description: Private is the filename of the mutual + TLS private key. + type: string + public: + description: Public is the filename of the mutual + TLS public key. + type: string + secret: + description: Secret is a secret with the mutual + TLS keys. + type: string + type: object + out: + description: |- + Out enables or disables TLS out on the + sidecar during replay. + type: boolean + type: object + type: object + tests: + description: |- + Tests are strings used to identify slices of inbound snapshot traffic this + workload is targeting and maps directly to a snapshot's `InTraffic` field. + Snapshot ingress traffic can be split across multiple slices where each + slice contains part of the traffic. A key must only be specified once + across all workloads, but a workload may specify multiple keys. Pass '*' + to match all keys. + + + Test strings may only match part of the snapshot's `InTraffic` key if the + string matches exactly one key. For example, the test string + `foo.example.com` would match the `InTraffic` key of + my-service:foo.example.com:8080, as long as no other keys would match + `foo.example.com` + + + This field is optional in the spec to provide support for single-workload + and legacy replays, but must be specified for multi-workload replays in + order to provide deterministic replay configuration. + items: + type: string + type: array + type: object + type: array + required: + - snapshotID + - testConfigID + type: object + status: + default: + observedGeneration: -1 + description: TrafficReplayStatus defines the observed state of TrafficReplay + properties: + active: + description: Active indicates whether this traffic replay is currently + underway or not. + type: boolean + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + finishedTime: + description: Information when the traffic replay has finished. + format: date-time + type: string + initializedTime: + description: Information when the test environment was successfully + prepared. + format: date-time + type: string + lastHeartbeatTime: + description: 'DEPRECATED: will not be set' + format: date-time + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation. + format: int64 + type: integer + reconcileFailures: + description: |- + ReconcileFailures is the number of times the traffic replay controller + experienced an error during the reconciliation process. The traffic + replay will be deleted if too many errors occur. + format: int64 + type: integer + reportID: + description: The id of the traffic replay report created. + type: string + reportURL: + description: The url to the traffic replay report. + type: string + startedTime: + description: Information when the traffic replay has started. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/deployments.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/deployments.yaml new file mode 100644 index 0000000000..e5f3292579 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/deployments.yaml @@ -0,0 +1,132 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + operator.speedscale.com/ignore: "true" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + labels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + {{- if .Values.globalLabels }} +{{ toYaml .Values.globalLabels | indent 4}} + {{- end }} + name: speedscale-operator + namespace: {{ .Release.Namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + strategy: + type: Recreate + template: + metadata: + annotations: + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 8}} + {{- end }} + labels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + {{- if .Values.globalLabels }} +{{ toYaml .Values.globalLabels | indent 8}} + {{- end }} + spec: + containers: + - command: + - /operator + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + envFrom: + - configMapRef: + name: speedscale-operator + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#container-v1-core + # When a key exists in multiple sources, the value associated with the last source will take precedence. + # Values defined by an Env with a duplicate key will take precedence. + - configMapRef: + name: speedscale-operator-override + optional: true + - secretRef: + name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}' + optional: false + image: '{{ .Values.image.registry }}/operator:{{ .Values.image.tag }}' + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + failureThreshold: 5 + httpGet: + path: /healthz + port: health-check + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + name: operator + ports: + - containerPort: 443 + name: webhook-server + - containerPort: 8081 + name: health-check + readinessProbe: + failureThreshold: 10 + httpGet: + path: /readyz + port: health-check + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 + resources: {{- toYaml .Values.operator.resources | nindent 10 }} + securityContext: + allowPrivilegeEscalation: false + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: false + # Run as root to bind 443 https://github.com/kubernetes/kubernetes/issues/56374 + runAsUser: 0 + volumeMounts: + - mountPath: /tmp + name: tmp + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: webhook-certs + readOnly: true + - mountPath: /etc/ssl/speedscale + name: speedscale-tls-out + readOnly: true + hostNetwork: {{ .Values.hostNetwork }} + securityContext: + runAsNonRoot: true + serviceAccountName: speedscale-operator + terminationGracePeriodSeconds: 10 + volumes: + - emptyDir: {} + name: tmp + - name: webhook-certs + secret: + secretName: speedscale-webhook-certs + - name: speedscale-tls-out + secret: + secretName: speedscale-certs + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/hooks.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/hooks.yaml new file mode 100644 index 0000000000..3e8231f194 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/hooks.yaml @@ -0,0 +1,73 @@ +--- +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + helm.sh/hook-weight: "4" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + name: speedscale-operator-pre-install + namespace: {{ .Release.Namespace }} + labels: + {{- if .Values.globalLabels }} +{{ toYaml .Values.globalLabels | indent 4}} + {{- end }} +spec: + backoffLimit: 0 + ttlSecondsAfterFinished: 30 + template: + metadata: + annotations: + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 8}} + {{- end }} + creationTimestamp: null + labels: + {{- if .Values.globalLabels }} +{{ toYaml .Values.globalLabels | indent 8}} + {{- end }} + spec: + containers: + - args: + - |- + # ensure valid settings before the chart reports a successfull install + {{- if .Values.http_proxy }} + HTTP_PROXY={{ .Values.http_proxy | quote }} \ + {{- end }} + {{- if .Values.https_proxy }} + HTTPS_PROXY={{ .Values.https_proxy | quote }} \ + {{- end }} + {{- if .Values.no_proxy }} + NO_PROXY={{ .Values.no_proxy | quote }} \ + {{- end }} + speedctl init --overwrite --no-rcfile-update \ + --api-key $SPEEDSCALE_API_KEY \ + --app-url $SPEEDSCALE_APP_URL + + # in case we're in istio + curl -X POST http://127.0.0.1:15000/quitquitquit || true + command: + - sh + - -c + envFrom: + - secretRef: + name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}' + optional: false + image: '{{ .Values.image.registry }}/speedscale-cli:{{ .Values.image.tag }}' + imagePullPolicy: {{ .Values.image.pullPolicy }} + name: speedscale-cli + resources: {} + restartPolicy: Never + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/rbac.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/rbac.yaml new file mode 100644 index 0000000000..e1ea42d999 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/rbac.yaml @@ -0,0 +1,244 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: speedscale-operator + {{- if .Values.globalAnnotations }} + annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }} + {{- end }} +rules: +- apiGroups: + - apps + resources: + - deployments + - statefulsets + - daemonsets + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - apps + resources: + - replicasets + verbs: + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - get + - list +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - clusterroles + verbs: + - get + - list +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps + - secrets + - pods + - services + - serviceaccounts + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - pods/log + verbs: + - get + - list +- apiGroups: + - "" + resources: + - events + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +- apiGroups: + - metrics.k8s.io + resources: + - pods + verbs: + - get + - list + - watch +- apiGroups: + - rbac.authorization.k8s.io + resources: + - rolebindings + - roles + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - networking.istio.io + resources: + - envoyfilters + - sidecars + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - security.istio.io + resources: + - peerauthentications + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - speedscale.com + resources: + - trafficreplays + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - speedscale.com + resources: + - trafficreplays/status + verbs: + - get + - update + - patch +- apiGroups: + - argoproj.io + resources: + - rollouts + verbs: + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: speedscale-operator + {{- if .Values.globalAnnotations }} + annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }} + {{- end }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: speedscale-operator +subjects: +- kind: ServiceAccount + name: speedscale-operator + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + creationTimestamp: null + labels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + name: speedscale-operator + namespace: {{ .Release.Namespace }} + {{- if .Values.globalAnnotations }} + annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }} + {{- end }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/secrets.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/secrets.yaml new file mode 100644 index 0000000000..1fb6999e4c --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/secrets.yaml @@ -0,0 +1,18 @@ +--- +{{ if .Values.apiKey }} +apiVersion: v1 +kind: Secret +metadata: + name: speedscale-apikey + namespace: {{ .Release.Namespace }} + annotations: + helm.sh/hook: pre-install + helm.sh/hook-weight: "3" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} +type: Opaque +data: + SPEEDSCALE_API_KEY: {{ .Values.apiKey | b64enc }} + SPEEDSCALE_APP_URL: {{ .Values.appUrl | b64enc }} +{{ end }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/services.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/services.yaml new file mode 100644 index 0000000000..f9da2c25c1 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/services.yaml @@ -0,0 +1,22 @@ +--- +apiVersion: v1 +kind: Service +metadata: + creationTimestamp: null + labels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + name: speedscale-operator + namespace: {{ .Release.Namespace }} + {{- if .Values.globalAnnotations }} + annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }} + {{- end }} +spec: + ports: + - port: 443 + protocol: TCP + selector: + app: speedscale-operator + controlplane.speedscale.com/component: operator +status: + loadBalancer: {} diff --git a/charts/speedscale/speedscale-operator/2.2.425/templates/tls.yaml b/charts/speedscale/speedscale-operator/2.2.425/templates/tls.yaml new file mode 100644 index 0000000000..4a24562884 --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/templates/tls.yaml @@ -0,0 +1,183 @@ +{{- $crt := "" -}} +{{- $key := "" -}} +{{- $s := (lookup "v1" "Secret" .Release.Namespace "speedscale-certs") -}} +{{- if $s -}} +{{- $crt = index $s.data "tls.crt" | b64dec -}} +{{- $key = index $s.data "tls.key" | b64dec -}} +{{ else }} +{{- $cert := genCA "Speedscale" 3650 -}} +{{- $crt = $cert.Cert -}} +{{- $key = $cert.Key -}} +{{- end -}} +--- +apiVersion: batch/v1 +kind: Job +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + helm.sh/hook-weight: "5" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + name: speedscale-operator-create-jks + namespace: {{ .Release.Namespace }} + labels: + {{- if .Values.globalLabels }} +{{ toYaml .Values.globalLabels | indent 4}} + {{- end }} +spec: + backoffLimit: 0 + ttlSecondsAfterFinished: 30 + template: + metadata: + annotations: + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 8}} + {{- end }} + creationTimestamp: null + labels: + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 8}} + {{- end }} + spec: + containers: + - args: + - |- + keytool -keystore /usr/lib/jvm/jre/lib/security/cacerts -importcert -noprompt -trustcacerts -storepass changeit -alias speedscale -file /etc/ssl/speedscale/tls.crt + kubectl -n ${POD_NAMESPACE} delete secret speedscale-jks || true + kubectl -n ${POD_NAMESPACE} create secret generic speedscale-jks --from-file=cacerts.jks=/usr/lib/jvm/jre/lib/security/cacerts + + # in case we're in istio + curl -X POST http://127.0.0.1:15000/quitquitquit || true + command: + - sh + - -c + volumeMounts: + - mountPath: /etc/ssl/speedscale + name: speedscale-tls-out + readOnly: true + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + envFrom: + - secretRef: + name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}' + optional: false + image: '{{ .Values.image.registry }}/amazoncorretto' + imagePullPolicy: {{ .Values.image.pullPolicy }} + name: create-jks + resources: {} + restartPolicy: Never + serviceAccountName: speedscale-operator-provisioning + volumes: + - name: speedscale-tls-out + secret: + secretName: speedscale-certs + {{- if .Values.affinity }} + affinity: {{ toYaml .Values.affinity | nindent 8 }} + {{- end }} + {{- if .Values.tolerations }} + tolerations: {{ toYaml .Values.tolerations | nindent 8 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }} + {{- end }} +--- +apiVersion: v1 +automountServiceAccountToken: true +kind: ServiceAccount +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + helm.sh/hook-weight: "1" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + labels: + app: speedscale-operator + controlplane.speedscale.com/component: operator + name: speedscale-operator-provisioning + namespace: {{ .Release.Namespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + helm.sh/hook-weight: "2" + creationTimestamp: null + name: speedscale-operator-provisioning +rules: +- apiGroups: + - "" + resources: + - secrets + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +- apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded + helm.sh/hook-weight: "3" + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + name: speedscale-operator-provisioning +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: speedscale-operator-provisioning +subjects: +- kind: ServiceAccount + name: speedscale-operator-provisioning + namespace: {{ .Release.Namespace }} +--- +apiVersion: v1 +kind: Secret +metadata: + annotations: + helm.sh/hook: pre-install + helm.sh/hook-delete-policy: before-hook-creation + {{- if .Values.globalAnnotations }} +{{ toYaml .Values.globalAnnotations | indent 4}} + {{- end }} + creationTimestamp: null + name: speedscale-certs + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + tls.crt: {{ $crt | b64enc }} + tls.key: {{ $key | b64enc }} diff --git a/charts/speedscale/speedscale-operator/2.2.425/values.yaml b/charts/speedscale/speedscale-operator/2.2.425/values.yaml new file mode 100644 index 0000000000..8f17c357ff --- /dev/null +++ b/charts/speedscale/speedscale-operator/2.2.425/values.yaml @@ -0,0 +1,138 @@ +# An API key is required to connect to the Speedscale cloud. +# If you need a key email support@speedscale.com. +apiKey: "" + +# A secret name can be referenced instead of the api key itself. +# The secret must be of the format: +# +# type: Opaque +# data: +# SPEEDSCALE_API_KEY: +# SPEEDSCALE_APP_URL: +apiKeySecret: "" + +# Speedscale domain to use. +appUrl: "app.speedscale.com" + +# The name of your cluster. +clusterName: "my-cluster" + +# Speedscale components image settings. +image: + registry: gcr.io/speedscale + tag: v2.2.425 + pullPolicy: Always + +# Log level for Speedscale components. +logLevel: "info" + +# Namespaces to be watched by Speedscale Operator as a list of names. +namespaceSelector: [] + +# Instructs operator to deploy resources necessary to interact with your cluster from the Speedscale dashboard. +dashboardAccess: true + +# Filter Rule to apply to the Speedscale Forwarder +filterRule: "standard" + +# Data Loss Prevention settings. +dlp: + # Instructs operator to enable data loss prevention features + enabled: false + + # Configuration for data loss prevention + config: "standard" + +# If the operator pod/webhooks need to be on the host network. +# This is only needed if the control plane cannot connect directly to a pod +# for eg. if Calico is used as EKS's default networking +# https://docs.tigera.io/calico/3.25/getting-started/kubernetes/managed-public-cloud/eks#install-eks-with-calico-networking +hostNetwork: false + +# A set of annotations to be applied to all Speedscale related deployments, +# services, jobs, pods, etc. +# +# Example: +# annotation.first: value +# annotation.second: value +globalAnnotations: {} + +# A set of labels to be applied to all Speedscale related deployments, +# services, jobs, pods, etc. +# +# Example: +# label1: value +# label2: value +globalLabels: {} + +# A full affinity object as detailed: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity +affinity: {} + +# The list of tolerations as detailed: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ +tolerations: [] + +# A nodeselector object as detailed: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/ +nodeSelector: {} + +# Deploy a demo app at startup. Set this to an empty string to not deploy. +# Valid values: ["java", ""] +deployDemo: "java" + +# Proxy connection settings if required by your network. These translate to standard proxy environment +# variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY +http_proxy: "" +https_proxy: "" +no_proxy: "" + +# control if sidecar init containers should run with privileged set +privilegedSidecars: false + +# control if the sidecar should enable/disable use of the smart dns lookup feature (requires NET_ADMIN) +disableSidecarSmartReverseDNS: false + +# Operator settings. These limits are recommended unless you have a cluster +# with a very large number of workloads (for eg. 10k+ deployments, replicasets, etc.). +operator: + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + # how long to wait for the SUT to become ready + test_prep_timeout: 10m + # timeout for deploying & upgrading control plane components + control_plane_timeout: 5m + + +# Default sidecar settings. Example: +# sidecar: +# resources: +# limits: +# cpu: 500m +# memory: 512Mi +# ephemeral-storage: 100Mi +# requests: +# cpu: 10m +# memory: 32Mi +# ephemeral-storage: 100Mi +# ignore_src_hosts: example.com, example.org +# ignore_src_ips: 8.8.8.8, 1.1.1.1 +# ignore_dst_hosts: example.com, example.org +# ignore_dst_ips: 8.8.8.8, 1.1.1.1 +# insert_init_first: false +# tls_out: false +# reinitialize_iptables: false +sidecar: {} + +# Forwarder settings +# forwarder: +# resources: +# limits: +# cpu: 500m +# memory: 500M +# requests: +# cpu: 300m +# memory: 250M +forwarder: {} diff --git a/index.yaml b/index.yaml index 7da0fffe2f..a87637caa3 100644 --- a/index.yaml +++ b/index.yaml @@ -5302,6 +5302,28 @@ entries: - assets/cloudcasa/cloudcasa-3.4.1.tgz version: 3.4.1 cockroachdb: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: CockroachDB + catalog.cattle.io/kube-version: '>=1.8-0' + catalog.cattle.io/release-name: cockroachdb + apiVersion: v1 + appVersion: 24.2.2 + created: "2024-09-24T00:54:28.680070753Z" + description: CockroachDB is a scalable, survivable, strongly-consistent SQL database. + digest: 6ff5688d354a7ee42a1b04c22a1a8774637545fa1fa7c7a8d9ad93f290901441 + home: https://www.cockroachlabs.com + icon: file://assets/icons/cockroachdb.png + kubeVersion: '>=1.8-0' + maintainers: + - email: helm-charts@cockroachlabs.com + name: cockroachlabs + name: cockroachdb + sources: + - https://github.com/cockroachdb/cockroach + urls: + - assets/cockroach-labs/cockroachdb-14.0.3.tgz + version: 14.0.3 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: CockroachDB @@ -9855,6 +9877,33 @@ entries: - assets/dh2i/dxoperator-1.0.1.tgz version: 1.0.1 dynatrace-operator: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Dynatrace Operator + catalog.cattle.io/kube-version: '>=1.19.0-0' + catalog.cattle.io/release-name: dynatrace-operator + apiVersion: v2 + appVersion: 1.3.0 + created: "2024-09-24T00:54:28.945354359Z" + description: The Dynatrace Operator Helm chart for Kubernetes and OpenShift + digest: aa0df689783816395a10d012ab84b25635bd10e12692ce0841c36f646742902e + home: https://www.dynatrace.com/ + icon: file://assets/icons/dynatrace-operator.png + kubeVersion: '>=1.19.0-0' + maintainers: + - email: marcell.sevcsik@dynatrace.com + name: 0sewa0 + - email: christoph.muellner@dynatrace.com + name: chrismuellner + - email: lukas.hinterreiter@dynatrace.com + name: luhi-DT + name: dynatrace-operator + sources: + - https://github.com/Dynatrace/dynatrace-operator + type: application + urls: + - assets/dynatrace/dynatrace-operator-1.3.0.tgz + version: 1.3.0 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: Dynatrace Operator @@ -36354,6 +36403,37 @@ entries: - assets/btp/sextant-2.2.21.tgz version: 2.2.21 speedscale-operator: + - annotations: + catalog.cattle.io/certified: partner + catalog.cattle.io/display-name: Speedscale Operator + catalog.cattle.io/kube-version: '>= 1.17.0-0' + catalog.cattle.io/release-name: speedscale-operator + apiVersion: v1 + appVersion: 2.2.425 + created: "2024-09-24T00:54:32.913353951Z" + description: Stress test your APIs with real world scenarios. Collect and replay + traffic without scripting. + digest: 59a90e087d9c1c8c0e09b0a652d24d4dfaf93fa1a3041dafd75ef15b9ac018bd + home: https://speedscale.com + icon: file://assets/icons/speedscale-operator.png + keywords: + - speedscale + - test + - testing + - regression + - reliability + - load + - replay + - network + - traffic + kubeVersion: '>= 1.17.0-0' + maintainers: + - email: support@speedscale.com + name: Speedscale Support + name: speedscale-operator + urls: + - assets/speedscale/speedscale-operator-2.2.425.tgz + version: 2.2.425 - annotations: catalog.cattle.io/certified: partner catalog.cattle.io/display-name: Speedscale Operator @@ -43019,4 +43099,4 @@ entries: urls: - assets/netfoundry/ziti-host-1.5.1.tgz version: 1.5.1 -generated: "2024-09-22T00:58:01.704748667Z" +generated: "2024-09-24T00:54:28.304548701Z"